#記事の概要
最近業務でdocker環境をkubernetes環境に移行することなり、
試行錯誤したことの備忘録です。
docker-compose.yamlをkubernetesの各種yamlに変換するには、
メジャーな選択肢として、komposeを使う方法があるようですが、
私の環境では上手く動作するyamlが作れませんでした。(根気不足)
そこでmacのDocker Desktopに付属のCompose on Kubernetesを
使ってみたところ、割りとスムーズにyaml変換ができました。
とりあえずkubenetes環境を動かせるyamlを手に入れられたことは、
作業の進捗とストレスの軽減に大いに寄与したので、今回はこの手順をまとめておきたいと思います。
7/26追記
その後、多少理解が進んで、追記を入れました。
永続ボリュームについてのyaml記述は、私の理解が不足しており、
とりあえず動かすというこの記事の目的にはそぐわないので削除しました。
まだ本番環境での運用に至っておりませんので、MySQLを永続化できてなくても間に合ってます…。
また理解が深まったら追記するか、別記事にあげようと思います。
##docker環境の準備
まずはdocker, docker-composeの環境があることが前提です。
また、mac版のDockerDesktopを使いますので、導入済みであることを前提に話を進めます。
今回は、membersedge社さんの記事からLaravelのdocker環境を、docker-compose.yamlのサンプルとして使用させて頂きました。(良記事のご提供をありがとうございます)
Laravel+docker環境構築手順、docker-compose.yaml記述の手順は本記事では触れませんので、ご了承ください。
###ビルド済みimageの準備
kubenetesにimage buildの機能はないため、docker側で済ませておく必要があります。
app:
build: ./docker/php
volumes:
- .:/var/www/html
docker-compose build
...
Successfully built 60a89dd016b0
Successfully tagged docker-compose-laravel-laravel_app:latest
###imageをリポジトリに入れる
今回は、ローカルリポジトリを作成して、そこにpushします。
詳しい手順はこちらを参照
docker run -d -p 5000:5000 --name registry registry:2
docker image tag docker-compose-laravel-laravel_app localhost:5000/docker-compose-laravel-laravel_app
docker push localhost:5000/docker-compose-laravel-laravel_app
#確認
curl http://localhost:5000/v2/_catalog
#作業が終わった後の消し方
docker container stop registry && docker container rm -v registry
ローカルリポジトリができたら、docker-compose.yaml内で
build指定をローカルリポジトリの参照に変更します。
※7/26追記
開発環境がローカル以外にあって、外部リポジトリサービスが使えるなら、
ローカル時点からそれを利用した方が便利でした。
app:
#build: ./docker/php
image: localhost:5000/docker-compose-laravel-laravel_app
volumes:
- .:/var/www/html
###kubenetesの利用開始
kubnetesを使い始めるので、DockerDeskTopのGUIで、kubenetes機能を有効にしておきます。
(Preference→kubenetes→Enable Kubernetes)
しばらく待つとkubnetesが利用できるようになり、
kubectlでserviceのステータスを見るとkubernetesのノードが起動しているとわかります。
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h7m
ここからが本題で
docker stack deployコマンドで、docker-compose.ymlからkubnetesを起動します。
※追記
docker stack deployコマンドの最後のappは任意のstack名です。
deploy後は、docker stack listで作成したstackを確認できます。
また、例では--namespace=testと、ネームスペースをtestに指定しています。
ネームスペースを指定する(default以外にする)場合、
docker stackコマンドでは--namespaceオプション
kubectlコマンドで-nオプションと
以後何をするにも、ネームスペースの指定が必要なことに注意してください。
kubectl create namespace test
docker stack deploy --orchestrator=kubernetes --namespace=test -c docker-compose.yml app
app: Ready [pod status: 1/1 ready, 0/1 pending, 0/1 failed]
web: Ready [pod status: 1/1 ready, 0/1 pending, 0/1 failed]
mysql: Ready [pod status: 1/1 ready, 0/1 pending, 0/1 failed]
続いて、service, pod, deploymentの、各構成要素を確認。
kubectl get services,pods,deployment -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/app ClusterIP None <none> 55555/TCP 8s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h11m
service/mysql ClusterIP None <none> 55555/TCP 8s
service/mysql-published LoadBalancer 10.105.55.206 localhost 3306:32600/TCP 8s
service/web ClusterIP None <none> 55555/TCP 9s
service/web-published LoadBalancer 10.98.109.219 localhost 8000:31960/TCP 8s
NAME READY STATUS RESTARTS AGE
pod/app-54b7f8b7db-btspb 1/1 Running 0 9s
pod/mysql-0 1/1 Running 0 8s
pod/web-6b4f4cc76b-xb9fn 1/1 Running 1 9s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/app 1/1 1 1 9s
deployment.extensions/web 1/1 1 1 9s
これだけで、mac環境においては、docker環境からkubenetes環境が構築できたことになります
何だ、じゃあ今時はdocker環境さえあればすぐkubenetes環境ができるんじゃん。
動かすだけなら、kubenetes覚える必要ないじゃん
そんな思考に心を奪われそうになりましたが、最終的にはAmazonLinux上で動かす必要があったので調べたところ、stack deployはDocker DesktopのEnterprise版のみの提供と分かりました
まあ、そう美味い話はないですよね。
しかしながら、今回の記事はそこを少し抵抗してみた話になります。
kubenetesは動作中の環境をkubenetes用のyamlにエクスポートする機能があるので、
これを使ってみました。
※7/26追記
pod.yamlは、deployment.yamlと内容が重複しており、
一旦なくても動くので、削除しました。
(pod.yamlでのみ、コンテナ初期化処理等が使えるのかも?)
mkdir k8s_manifest
kubectl get service -o yaml -n test > k8s_manifest/service.yaml
kubectl get deployment -o yaml -n test > k8s_manifest/deployment.yaml
きちんとyamlが出力されました。
Linux環境ではstack deployが使えないといっても、kubenetes本来の環境構築マニフェストのyamlが出力がされたなら、それを使って環境構築できそうなものです。
出力された各yamlから環境起動できるかを試してみます。
その前に、stack deployした環境の終了方法から。
docker stack rm --orchestrator=kubernetes --namespace=test app
そして、各種yamlからのkubenetes環境起動。
kubectl apply -f k8s_manifest/
結論をいえば上記は起動しませんでした
ここで、幾つかの箇所を修正することで起動するに至りましたので、
ご紹介しておきたいと思います。
以下のように、
deployment.yaml, serice.yaml内の
ownerReferencesブロックを全削除してください。
#ownerReferences:
#- apiVersion: compose.docker.com/v1alpha3
# blockOwnerDeletion: true
# controller: true
# kind: Stack
# name: app
# uid: 47a61263-8eda-11ea-9393-025000000001
同様にservice.yamlにおいても、
ownerReferencesブロックを全削除してください。
#ownerReferences:
#- apiVersion: compose.docker.com/v1alpha3
# blockOwnerDeletion: true
# controller: true
# kind: Stack
# name: xxx
# uid: 26c6de60-b890-4b41-9cac-c9bafa8a43d3
namespaceが「default」の場合、
service.yaml内に
マスターノードの定義が含まれるので、それも削除します。
※本記事の手順通りであればnamespaceを「test」にしているので、
マスターノードの定義は現れません。
# - apiVersion: v1
# kind: Service
# metadata:
# creationTimestamp: "2020-05-05T10:59:51Z"
# labels:
# component: apiserver
# provider: kubernetes
# name: kubernetes
# namespace: default
# resourceVersion: "426818"
# selfLink: /api/v1/namespaces/default/services/kubernetes
# uid: 2312e5e3-ab09-4c1a-ae86-abd4df9876cb
# spec:
# clusterIP: 10.96.0.1
# ports:
# - name: https
# port: 443
# protocol: TCP
# targetPort: 6443
# sessionAffinity: None
# type: ClusterIP
# status:
# loadBalancer: {}
次に、service.yaml内の
spec.typeが「LoadBalancer」の箇所で、
spec.clusterIPとspec.NodePortを削除してください。
これらを固定にしておくと、他クラスタ割当のものと衝突する場合がありました。
※spec.typeがClusterIPの箇所は削除しません。
クラスタ内でのDNS参照(headlessサービス等)に必要なようです。
spec:
#clusterIP: 10.105.151.173(削除)
externalTrafficPolicy: Cluster
ports:
- name: 8000-tcp
#nodePort: 31427(削除)
port: 8000
protocol: TCP
targetPort: 80
selector:
com.docker.service.id: xxx
com.docker.service.name: xxx
com.docker.stack.namespace: xxx
sessionAffinity: None
type: LoadBalancer
deployment.yamlとservice.yamlの各ブロックから
「resourceVersion」と「uid」も削除してください。
残しておくと、更新時の管理が難しくなりました。
固定値はなるべく消して、シンプルにすると良い感じです。
あとはEKSの開発環境ではhostPathが使えないので、とりあえずvolumesの指定ごと削除しています。
spec.template.spec.containers以下
#volumeMounts:
# - mountPath: /var/www/html
# name: mount-0
# subPath: src
#volumes:
# - hostPath:
# path: /Users/xxx/workspace
# type: ""
# name: mount-0
まだ他に無駄な箇所があるかもしれませんが、一旦以上です。
修正後に、改めて起動
kubectl apply -f k8s_manifest/
私の環境ではこれで起動しました。
本来のkubenetesのマニフェストから動かすことができ、docker環境からkubenetes環境への移行が叶いました
後はkubectl execでpodにログインして、Laravel等の設定を行うのみです。
これからkubenetesに触れられる方にとって、この記事が少しでも手助けになることができましたら幸いです。