概要
今日は、zlabjp/kubernetes-resource を実際に使うというのをやります。kubernetes-resource は、k8s にアプリケーションをデプロイするための concourse リソースです。ゼットラボで必要に迫られて作って、それから便利に使っています。@superbrothers による初日の記事の通りです。ツールというのは、あれこれ触ってみると理解が進みます。手元に k8s クラスタと concourse があって、GitHub と Docker Hub を利用できる環境であれば、同じことができるはずです。よかったら一緒にやりましょう。
やること
あらかじめ k8s に nginx-1.13.6 をデプロイしておいて、concourse から nginx-1.13.7 にアップデートします。あらかじめの方は、手元の PC から個人の権限でデプロイします。アップデートの方は、GitHub リポジトリの Tag の作成をトリガーにして、concourse から ServiceAccount の権限でデプロイします。k8s と kubectl のバージョンは、ともに v1.7.11 を使います。大きくは、準備して実行するだけです。
準備
GitHub → k8s → concourse の順に準備します。
GitHub
今回は、bhiro/myproject
というリポジトリを新しく Private で作りました。README.md もリポジトリと一緒に作りました。これを手元の PC に git clone します。
$ git clone git@github.com:bhiro/myproject.git
$ cd myproject
このリポジトリを concourse から Read するための Deploy key を作成します。Deploy Key の実体は、SSH キーペアです。このキーペアは、concourse が使います。パスフレーズは設定してはいけません。no passphrase
でないと concourse のジョブが失敗します。作成した鍵は、secrets ディレクトリに保存します。
$ mkdir secrets
$ ssh-keygen -t rsa -b 4096 -C "" -f secrets/id_rsa
公開鍵は、GitHub リポジトリの Deploy Keys に Read only の設定で登録します。秘密鍵は、あとで concourse パイプラインに登録します。
secrets
├── id_rsa
└── id_rsa.pub
secrets ディレクトリは、誤って Git にコミットしないように、.gitignore
に書いておきます。
/secrets
k8s
定義ファイルを作ってから、k8s リソースを作ります。
定義ファイル
k8s の定義ファイルを作ります。作り終えると、手元の PC のディレクトリは、以下のようになります。
myproject
├── .git
├── .gitignore
├── README.md
├── deploy
│ └── nginx-deploy.yaml
├── k8s
│ ├── 0_ns.yaml
│ ├── role.yaml
│ ├── rolebinding.yaml
│ └── sa.yaml
└── secrets
├── id_rsa
└── id_rsa.pub
k8s ディレクトリには、クラスタ向けの定義ファイルを置きます。deploy ディレクトリには nginx 向けの定義ファイルを置きます。以下は、定義ファイルの一覧です。
| 定義ファイル | リソース種別 | リソース名 |
| --- | --- | --- | --- |
| k8s/ns.yaml | Namespace | dev |
| k8s/sa.yaml |Service Account | deploy |
| k8s/role.yaml | Role | deploy |
| k8s/rolebinding.yaml | RoleBinding | deploy |
| deploy/nginx-deploy.yaml | Deployment | nginx |
ファイルの内容は以下の通りです。
dev ネームスペースです。
apiVersion: v1
kind: Namespace
metadata:
name: dev
deploy という ServiceAccount と Role を作って、それらをバインドします。これらのリソースは、dev ネームスペースに置きます。
apiVersion: v1
kind: ServiceAccount
metadata:
name: deploy
namespace: dev
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: deploy
namespace: dev
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["extensions"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["autoscaling"]
resources: ["*"]
verbs: ["*"]
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: deploy
namespace: dev
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: deploy
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: system:serviceaccount:dev:deploy
namespace: dev
nginx-1.13.6 をデプロイするための、Deployment です。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.13.6
name: nginx
リソース
kubectl コマンドを使って、手元の PC から k8s リソースを作ります。先にクラスタ向けのリソースを作ります。
$ kubectl apply -f k8s/
それから、nginx 向けのリソースを作ります。
$ kubectl apply -f deploy/ --namespace=dev
すでに定義ファイルがあるので簡単ですね。
pod が Running で nginx-1.13.6 のイメージなら OK です。
$ kubectl get pod --namespace=dev
NAME READY STATUS RESTARTS AGE
nginx-1161159442-nlvzx 1/1 Running 0 5m
$ kubectl describe pod nginx-1161159442-nlvzx --namespace=dev |grep 'Image:'
Image: nginx:1.13.6
concourse
定義ファイル
concourse の定義ファイルを作ります。作り終えると、手元の PC のディレクトリは、以下のようになります。
myproject
├── .git
├── .gitignore
├── README.md
├── concourse
│ └── pipeline.yaml
├── deploy
│ └── nginx-deploy.yaml
├── k8s
│ ├── 0_ns.yaml
│ ├── role.yaml
│ ├── rolebinding.yaml
│ └── sa.yaml
└── secrets
├── concourse-secrets.yaml
├── id_rsa
└── id_rsa.pub
concourse ディレクトリにパイプライン向けの定義ファイルを置きます。秘密情報は、Git にコミットされないように secrets ディレクトリに置きます。以下は、定義ファイルの一覧です。
定義ファイル |
---|
concourse/pipeline.yaml |
secrets/concourse-secrets.yaml |
pipeline.yaml の内容は以下の通りです。
最初に kubernetes-resource の定義があります。tag
は、デプロイ先の k8s のマイナーバージョンに合わせてセットします。今回のデプロイ先は k8s-v1.7.11 なので、tag: "1.7"
としています。{{key}}
と {{config}}
は秘密情報です。パイプライン作成時に、concourse-secrets.yaml から展開します。
resource_types:
- name: kubernetes
type: docker-image
source:
repository: zlabjp/kubernetes-resource
tag: "1.7"
resources:
- name: myproject
type: git
source:
uri: git@github.com:bhiro/myproject.git
branch: master
tag_filter: v*
private_key: {{key}}
- name: myk8s
type: kubernetes
source:
kubeconfig: {{config}}
jobs:
- name: deploy
serial: true
plan:
- get: myproject
trigger: true
- put: myk8s
params:
kubectl: apply -f myproject/deploy --namespace=dev
wait_until_ready_selector: app=nginx
次に、concourse-secrets.yaml を作ります。
concourse-secrets.yaml には、GitHub リポジトリを Read するための Deploy Key と、k8s クラスタを操作するための kubeconfig を記入します。Deploy key には、GitHub の準備で作成した SSH キーペアの秘密鍵を使います。
$ cat secrets/id_rsa > secrets/concourse-secrets.yaml
$ chmod 600 secrets/concourse-secrets.yaml
kubeconfig は、zlabjp/kubernetes-scripts に含まれる create-kubeconfig というツールを使ってジェネレートします。create-kubeconfig の引数は ServiceAccount 名です。k8s の準備で dev ネームスペースに作成した deploy サービスアカウント を渡します。
$ curl -LO https://raw.githubusercontent.com/zlabjp/kubernetes-scripts/master/create-kubeconfig
$ chmod +x ./create-kubeconfig
$ mv ./create-kubeconfig /tmp/
$ /tmp/create-kubeconfig deploy --namespace=dev >> secrets/concourse-secrets.yaml
key と config をキーとして yaml に整形します。ここは、エディタの矩形編集を使って頑張ります。
key: |
-----BEGIN RSA PRIVATE KEY-----
....
....
-----END RSA PRIVATE KEY-----
config: |
apiVersion: v1
....
....
token: ....
これで、全ての定義ファイルが揃いました。最後に GitHub に Push しておきます。
$ git add -A
$ git commit -m "create definition files"
$ git push origin master
パイプライン
fly コマンドを使って、手元の PC から concourse のパイプラインを作ります。${URL}
と ${TEAM}
は、環境に合わせてセット下さい。ターゲット名とパイプライン名は任意です。今回はそれぞれ dev, myproject としています。
$ fly --target dev login --concourse-url ${URL} --team-name ${TEAM}
$ fly --target dev set-pipeline --pipeline myproject --config concourse/pipeline.yaml --load-vars-from secrets/concourse-secrets.yaml
$ fly --target dev unpause-pipeline --pipeline myproject
すでに定義ファイルがあるので簡単ですね。
UI や コマンドラインからパイプラインが確認できれば OK です。
$ fly --target dev pipelines
実行
実行は、準備よりだいぶ簡単です。GitHub リポジトリ の Tag の作成をトリガーにして、k8s 上の nginx-1.13.6 を concourse から nginx-1.13.7 にアップデートします。
nginx-deploy.yaml を以下のように変更します。
git diff deploy/nginx-deploy.yaml
diff --git a/deploy/nginx-deploy.yaml b/deploy/nginx-deploy.yaml
index ec17270..4a8c9a9 100644
--- a/deploy/nginx-deploy.yaml
+++ b/deploy/nginx-deploy.yaml
@@ -14,5 +14,5 @@ spec:
app: nginx
spec:
containers:
- - image: nginx:1.13.6
+ - image: nginx:1.13.7
name: nginx
コミットして push します。
$ git add deploy/nginx-deploy.yaml
$ git commit -m "update nginx"
$ git push origin master
最後に Tag を切ります。
$ git tag v0.0.1
$ git push origin v0.0.1
これを、トリガーに concourse の job が動きます。
$ fly --target dev builds|grep myproject
2674 myproject/deploy 1 succeeded 2017-12-06@20:04:26+0900 2017-12-06@20:04:48+0900 22s
22秒で終わりました。成功したようです。UI も job の成功を表す緑色になっています。
k8s を確認します。
$ kubectl get pod --namespace=dev
NAME READY STATUS RESTARTS AGE
nginx-3944497639-tzk71 1/1 Running 0 3m
$ kubectl describe pod nginx-3944497639-tzk71 --namespace=dev |grep 'Image:'
Image: nginx:1.13.7
確かに、nginx-1.13.7 にアップデートされています。
まとめ
今日は、zlabjp/kubernetes-resource を使って、concourse から k8s へのデプロイをやりました。CI や CD の準備というのは大変なものですが、組み終わって、動き出すと、なんとも気持ちのいいものです。ぜひ、お試しください。
おわりに
このエントリは、弊社 Z Lab のメンバーによる Z Lab Advent Calendar 2017 の十一日目として業務時間中に書きました。十二日目は @TakanariKo による OpenFaaS のお話です。