JAZUG札幌支部(きたあず) 第22回勉強会~Azure Kubernetes Service(AKS) ハッカソン~を開催しました

今回のJAZUG札幌支部「きたあず」勉強会はMicrosoftの寺田佳央さんに来て頂きまして、「Kubernetesハッカソン」として開催しました。

きたあずとしては初のハッカソンで、2日間終日開催という全くゆるくない勉強会でした。

この勉強会で得られた知見
  • DockerイメージのビルドからKubernetesクラスタへのデプロイを一通り理解出来た
  • ServiceでLoadBlancerを使用しない
  • ポータビリティに注意

概要説明と準備

まず寺田さんによるコンテナからKubernetesまでの概要説明があり、その後は実際にチームになってハッカソンをしました。

今回のゴールを設定する

まず、みんなでポストイットに「今回のハッカソンでやりたいこと」を記入しホワイトボードに貼り付けました。

この「やりたいこと」をベースに寺田さんが流れをアレンジしてハッカソンを進めていきました。

実際のハッカソンの流れ

今日の流れとハマりポイントをメモ。(主に自分用)

APIを返すDockerを作成した

まず、Kubernetes上にデプロイ・動作させるDockerコンテナを作るところから始めました。

http://example.com/api/values

とリクエストを投げると、

["value1"],["value2"]

というレスポンスを返すようなコンテナを作成しました。

ハマりポイント

  • VisualStudioで生成されるDockerfileだと、パスの問題でbuild出来なかった
  • VSで生成されたDockerfileは、特にディレクトリ遷移まわりを見直す必要がある。

コンテナをAzure Container Registoryにpush

ビルドしたdockerイメージをAzure Container Registoryにpushするには、まず事前に追加したContainer Registoryにログインする。

$ docker login -u kitaazu22 kitaazu22.azurecr.io
$ sudo docker push kitaazu22/application:1
注意
タグ(「application:1」の「1」の所)は必ず設定すること。また、「latest」は指定しないこと。

Container RegistoryとKubernetesの認証設定

kubectlコマンドでContainer RegistoryからDockerイメージを取得出来るようにするには、認証情報(secret)を設定する必要がある。

$ kubectl create secret docker-registry docker-reg-credential \
--docker-server=kitaazu22.azurecr.io \
--docker-username=username \
--docker-password=xxxxxxxxxxxxxxxxxxxxxxx \
--docker-email=foo-bar@example.com

出来たかどうかを行う

$ kubectl get secret

結果はこうなる

NAME                    TYPE                                  DATA   AGE
default-token-c98jz     kubernetes.io/service-account-token   3      25h
docker-reg-credential   kubernetes.io/dockerconfigjson        1      21h

serviceの設定

KubernetesのPodは各ノードに分散されるため、外部からの通信リクエストに一元的に応答させるには、一定の固定IPが必要になる。serviceを指定してエンドポイントを準備する。

service.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: kitaazu22-service
  name: kitaazu22-service
spec:
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: kitaazu22-service
    version: v3
  sessionAffinity: None
  type: ClusterIP

サービスをこれで登録する。

$ kubectl apply -f sample-externalip.yaml
ハマりポイント
・ typeはClusterIPにする。
・LoadBalancerは本番環境では使用しないこと

ingressの設定

次に、外部からの通信を受け付けるためにingressを設定する。

通信の流れを、「 インターネット → service」 ではなく、「インターネット → ingress → service 」にする。

ingress.yaml

kind: Ingress
metadata:
  name: kitaazu22
  annotations:
    kubernetes.io/ingress.class: addon-http-application-routing
spec:
  rules:
  - host: kitaazu22.hogehogoehogeabb25d.eastus.aksapp.io
    http:
      paths:
      - backend:
          serviceName: kitaazu22-service
          servicePort: 80
        path: /

そして適用する。

$ kubectl apply -f ingress.yaml

デプロイ設定

クラスタへのデプロイ設定を記述する。ここで、ローリングアップデートを設定したり、使用するコンテナを指定出来る。

deployment.yaml

eployment.yml 
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: kitaazu22-service
spec:
  replicas: 2
  selector:
    matchLabels:
     app: kitaazu22-service
  template:
    metadata:
      labels:
        app: kitaazu22-service
        env: test
        version: v1
    spec:
      imagePullSecrets:
        - name: docker-reg-credential
      containers:
      - name: kitaazu22-service
        image: kitaazu22.azurecr.io/kitaazu22app:1

deployment.yamlをKubernetesに適用する。

$ kubectl apply -f deployment.yaml

ローリングアップデート

新しいコンテナをデプロイする際、サービスを止めること無くアップデートを行う。この方法を使うと、クラスタ内のレプリカを少しずつ差し替えしていくことで、無停止アップデートを行うことが出来る。

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: kitaazu22-service-fuwa
spec:
  minReadySeconds: 20
  progressDeadlineSeconds: 600
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 50%
      maxUnavailable: 30%
  replicas: 3
  selector:
    matchLabels:
     app: kitaazu22-service
  template:
    metadata:
      labels:
        app: kitaazu22-service
        env: test
        version: v3
    spec:
      imagePullSecrets:
        - name: docker-reg-credential
      containers:
      - name: kitaazu22-service-fuwa
        image: kitaazu22.azurecr.io/kitaazu22:5
        livenessProbe:
          httpGet:
            path: /api/healthx
            port: 80
          initialDelaySeconds: 20
          timeoutSeconds: 5
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /api/healthy
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 10
          failureThreshold: 5

感想

知識の整理が必要

仕事ではKubernetesを使っておらず、夜の仕事の研究枠でAKSやRacncherOSを使ってきました。業務で使えるようになるべく自分の環境でKubernetesクラスターを作ったりしてきたのですが、断片的な情報で構築していたため、知識の抜けが出ていました。

今回のハッカソンでも知識の抜けが表面に出てしまい、実際に自分が皆の前でkubectlコマンドを打ち込む際にも手間取ってしまいました。

今回のハッカソンでは、全員が1つのチームとなって教えあいながら進めることが出来たため、自分自身の問題に気づくことが出来ました。これは非常に大きな成果だと思っています。このような機会が無いと自分の問題に気づけませんし、改善を図るチャンスも得られなかったと思います。

ハマりポイントの発見

また、結構kubectlやDockerのビルドまわりでミスをしながらハマりポイントを見つけることが出来たのも収穫かなと思っています。こういう所でどんどんミスをしていかないと、大事な時にミスって事故を招いちゃうので・・・

英語力

「英語のドキュメントをどんどん読んでいかないと追いつかない」という寺田さんの言葉にはとても共感しました。

英語のドキュメントはなかなか日本語訳されないし、日本語訳が来るのを待ってるとその分世界的に取り残されちゃうんですよね。

私自身も同じ事を考えているのですが、「日本語化への協力」という形で対応してきました。

Microsoft Azureのdocsの日本語を直してみた

ただ寺田さんとの会話で、それも限界に近いと感じました。発信されてくる情報は日々増えており、元情報は全て英語です。そのため、いくら翻訳や修正に協力してもどこかで破綻するような気づきが得られました。英語の文章を和訳すること無くそのまま理解し、知識化することが今後エンジニアには重要になると確信することが出来ました。

とりあえず、私はAzure Portalの言語設定を英語にするところからスタートしました。