kubell Creator's Note

ビジネスチャット「Chatwork」のエンジニアのブログです。

ビジネスチャット「Chatwork」のエンジニアのブログです。

読者になる

Kubernetesをめぐる冒険、の後日譚

Chatwork 坂本です。

本ブログは2020年1月23日に行われた、下記のコンテナ支部での発表を補足する内容で、eksctlの設定ファイルとvariantの具体的な使い方に焦点を当てて書きたいと思います。

jawsug-container.connpass.com

speakerdeck.com

目次

eksctlの設定ファイル

発表資料では、主にeksctlをvariantでwrapして、運用している、という話をしましたが(さらにeksctlの設定ファイルのテンプレートからの生成もvariantで)、そもそもなんでそのような運用が必要なのか、というのを、eksctlの設定ファイルの構成から説明していきたいと思います。

下記がChatworkで運用しているeksctlの設定ファイルのサンプルです(eksctl version 0.13.0)。

eks本体の設定ファイル:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: %%CLUSTER_NAME%%
  region: ap-northeast-1
  version: "%%EKS_VERSION%%"

cloudWatch:
  clusterLogging:
    enableTypes: ["*"] # types: "api", "audit", "authenticator", "controllerManager", "scheduler"

vpc:
  clusterEndpoints:
    privateAccess: true
    publicAccess: true

  publicAccessCIDRs:
  - "XX.XX.XX.XX/32"

  subnets:
    # must provide 'private' and/or 'public' subnets by availibility zone as shown
    public:
      ap-northeast-1b:
        id: "subnet-XXXXX"
      ap-northeast-1c:
        id: "subnet-XXXXX"
      ap-northeast-1d:
        id: "subnet-XXXXX"

nodegroupの設定ファイルの一部:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: %%CLUSTER_NAME%%
  region: ap-northeast-1

nodeGroups:
- name: worker-1b-%%WORKER_VERSION%%
  labels:
    node.kubernetes.io/role: "worker"
    aws.amazon.com/purchaseType: "spot"
  instanceType: mixed
  minSize: 1
  maxSize: 40
  desiredCapacity: %%WORKER_DESIRED_CAPACITY%%
  volumeSize: %%WORKER_VOLUME_SIZE%%
  volumeType: gp2
  volumeEncrypted: true
  instancesDistribution:
    instanceTypes:
    - m5.xlarge
    - c5.xlarge
    - c5n.xlarge
    - c4.xlarge
    onDemandBaseCapacity: 0
    onDemandPercentageAboveBaseCapacity: 0
    spotInstancePools: 4
  tags:
      # EC2 tags required for cluster-autoscaler auto-discovery
      k8s.io/cluster-autoscaler/enabled: "true"
      k8s.io/cluster-autoscaler/%%CLUSTER_NAME%%: "owned"
  iam:
    instanceProfileARN: "arn:aws:iam::XXXXXXX:instance-profile/eks-nodegroup-worker"
    instanceRoleARN: "arn:aws:iam::XXXXXXX:role/eks-nodegroup-worker"
  preBootstrapCommands:
  - 'cat /etc/docker/daemon.json | jq -r ".\"log-opts\".\"max-size\" |= \"%%WORKER_LOG_MAX_SIZE%%\"" | jq -r ".\"log-opts\".\"max-file\" |= \"%%WORKER_LOG_MAX_FILE%%\"" > /tmp/docker.json'
  - 'cp -f /tmp/docker.json /etc/docker/daemon.json'
  - 'systemctl restart docker'
  securityGroups:
    attachIDs:
    - "sg-XXXXX"
  availabilityZones:
  - "ap-northeast-1b"

eksctlとしてはなかなか複雑な設定ファイルだと思いますが、このような設定ファイルにしているのは下記の理由があります。

  • nodegroupは、新しい機能が入ったり、amiが新しくなったりして、作り直すことがあるので、単独で管理したい
    • 見やすい
    • 作り直しに対応しやすいように、nodegroupにversionを付けている(dateの結果が%%WORKER_VERSION%%に入る)
  • managed nodegroupは使わない(使えない)
    • spotに対応していない
      • ChatworkではKubernetes化に伴い(かつ、最近のspotの安定性を考慮し)、本番環境もspotでの運用を目指しています
    • preBootstrapCommandsに対応していない
  • cluster-autoscalerを利用するため、az毎にnodegroupを作成する
    • 上記は1bだけですが、1c, 1dも同じ内容で作成します
    • cluster-autoscalerを利用する際、1つのazにまとめてしまうと、cluster-autoscalerとしては、どのazを広げるべきなのか判断できないため、個別に作成する必要があります
  • その他、volumesizeなど、環境毎(prod,stg,test)に変えたい

これらの設定がありますが、クラスタ毎で変わるのはそれほどありません。 そのため、上記の内容をテンプレート化して、吐き出し、それをeksctlコマンドに渡して、eks、eks nodegroupを作成しています。

eksctlの設定ファイルのsampleは下記で確認できます。

まれに上記にない項目もありますが、その場合はソースを見るしかないです。 https://github.com/weaveworks/eksctl/blob/master/pkg/apis/eksctl.io/v1alpha5/types.go

preBootstrapCommandsについて

非managed node groupを利用する場合、preBootstrapCommandsが利用できます。 preBootstrapCommandsは、userdataとして実行されるもので、これによって、eksctl自体で対応できない設定も対応することが可能な場合があります。

preBootstrapCommandsをuserdataとして登録するのは、ソースコードでは↓です。

https://github.com/weaveworks/eksctl/blob/master/pkg/cfn/builder/nodegroup.go

上記の設定ファイルのpreBootstrapCommandsでは

  • defaultのdockerの設定(/etc/docker/daemon.json)の一部をjqコマンドで置換
    • amazon linux2はデフォルトでjqが入っている
  • dockerのrestart

を実行しています。具体的には、dockerのログローテーションの設定をしています。デフォルト(10Mが10file)でも問題ありませんが、本番環境だけ不安なので、大きめにしています(その分、nodeのvolumesizeも大きめに)。

このdockerの設定は、下記で見つけて導入しました。他にも使えるものがあるので、いろいろと設定したい場合は、exampleを漁ってみてください。 https://github.com/weaveworks/eksctl/blob/master/examples/05-advanced-nodegroups.yaml

githubのexampleにしかないものもあるし、eksctl.ioのドキュメントにしかないものがある場合があるため、両方見てみることをおすすめします。

variantの具体的な使い方

variantの詳細な機能を説明するわけではないですが、発表資料よりもう少し具体的なvariantの使い方を説明します。

github.com

上記のようなテンプレートからeksctlの設定ファイルを生成していますが、以外と値が多く、sedでやるとしてもなかなか骨が折れる内容ではあります。

そこで、Chatworkではvariantの設定ファイルを作成し、それを環境毎に持ち、variant経由でコマンドを実行しています。

variantの設定ファイルたち

$ tree config
config
└── environments
    ├── eks-prod.yaml
    ├── eks-stg.yaml
    └── eks-test.yaml

これらのファイルの中身は下記のような内容です。

% cat config/environments/eks-prod.yaml
awsProfile: ""
awsDefaultRegion: "ap-northeast-1"
awsAccessKeyId: ""
awsSecretAccessKey: ""
eksVersion: "1.14"

worker:
  desiredCapacity: "2"
  volumeSize: "200"
  log:
    maxSize: "50m"
    maxFile: "6"

そして、これをvariantの環境として実行すれば、eks-prod用のeksctl設定ファイルが生成されます。 variantではファイル名がコマンド名になり、Chatworkではeksを管理するコマンドをachlisとしています。

# env setはvariant自身のコマンド
./achlis env set "eks-prod"

# ファイルの生成
## generateコマンドの実体は、configに設定された値でひたすらsedで置換するものです
./achlis generate files --aws-profile=XXXX

# born
./achlis born

環境毎の設定をファイルに持たせることができるので、コマンド自体は変わらず、再現性が高くなり、設定をgitで管理することができます。 またvariantにはdocker runner機能(コマンドをdocker runで実行する)があるため、環境とコマンドがセットになります。

さらに、発表資料でも書きましたが、bornというコマンドの中では、実際には

  • EKS cluster 作成
  • nodegroup 作成
  • iamserviceaccount 作成
  • flux enable repo の有効化(fluxのinstall)

がステップ実行されます(variantはtask runner)。

あとはCIや人間が、achlisを実行すれば、どんどんEKSのclusterができていきます。

まとめ

  • eksctl!!
  • variant !!

上記のachlisはvariant1で作成しましたが、variant2に移行中です。

github.com

variant2ではtestや、並列実行、ログ周りなどいろいろと改善されております。

最後に(どうでもいいニュース)

ランナーしての活動を報告しますと、2020年2月に行われた神奈川マラソン(ハーフマラソン)で、89分46秒で完走し、無事にハーフマラソンの自己ベストを更新しました。

ハーフマラソン90分切りは1つの目標であり、今のトレーニングが順調に来ていることを確認できるいい機会でした。 3月に行われる板橋シティマラソンで、どれぐらいいけるのか、非常に楽しみではありますが、同時に怖さもあります。

以上です。