Edited at

EKSにデプロイしたGitLabとS3を連携させる


はじめに

EKSにHelmでGitLabをデプロイする際、デフォルトではminioをオブジェクトストレージとして使用していますが、今回はS3でそれらを代替する方法を説明します。


前提


  • EKSクラスタが構築済みであること

  • EKSワーカーノードがデプロイされていること(今回はt3.medium×3個構成)

  • 操作用マシンにAWS CLI、kubectl、Helmがインストールされていること


手順

大きく分けて4つの手順があります。

1. オブジェクトストレージとしてS3バケットを用意する。

2. PodがS3にアクセスできるようにkube2iamを設定する。

3. S3にアクセスするための認証情報をKubernetes Secretから設定する。

4. GitLab Helm Chartに編集を加えてEKSにデプロイする。

説明の中で使われている<RELEASE>はHelmのRelease名です。自分の好きな名前に変換してください。


1. S3バケットの用意

事前にS3バケットを作成しておく必要があります。全部で9個のバケットを作成します。1個のバケットでパスで分けれれば楽なんですがまだ実装されていないようです。

バケット名は何でも良いですが、Release名と目的が明確になるようにしましょう。

バケット名
内容

1
<RELEASE>-gitlab-artifacts
ビルドジョブを行ったときの成果物

2
<RELEASE>-gitlab-backups
アプリケーションバックアップを行うときに作成されるバックアップファイル

3
<RELEASE>-gitlab-lfs
サイズの大きいファイル

4
<RELEASE>-gitlab-mr-diffs
マージリクエストのdiff

5
<RELEASE>-gitlab-packages
アプリや依存ツールのパッケージ

6
<RELEASE>-gitlab-pseudo
アプリデータを安全にエクスポートしたもの

7
<RELEASE>-gitlab-registry
Dockerレジストリイメージ

8
<RELEASE>-gitlab-tmp
リストアを行うときに一時的に置いておく現存データ

9
<RELEASE>-gitlab-uploads
アイコン画像などのアップロードファイル




AWSコンソール画面は次のようになります。Release名はsampleにしました。

スクリーンショット 2019-08-13 14.49.44.png


2. kube2iamの設定


IAMロールの作成

PodがS3にアクセスするためにkube2iamを使ってIAMロールをPodにアタッチします。他にもIAMユーザの権限を与えるかIAMロールをワーカーノードにアタッチする方法もありますが、前者はアクセスキーとシークレットアクセスキーをPodに設定する点がイケてなく、後者は関係ないPodもS3にアクセスできてしまう点でイケてないです。

まずはワーカーノードについて考えます。次のようにIAMポリシーを定義したjsonファイルをまず作成します。


assume-role-policy.json

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
}
]
}

次にjsonファイルからIAMポリシーを作成します。

$ aws iam create-policy \

--policy-name assume-role-policy \
--policy-document file://assume-role-policy.json

ワーカーノードにアタッチされているIAMロールにこのポリシーをアタッチします。<NODE_INSTANCE_ROLE>はCloudFormationの出力タブで確認できる、XXXX-NodeInstanceRole-XXXXという値です。<YOUR_ACCOUNT>は12桁のAWSアカウントIDです。

$ aws iam attach-role-policy \

--role-name <NODE_INSTANCE_ROLE> \
--policy-arn arn:aws:iam::<YOUR_ACCOUNT>:policy/assume-role-policy

ワーカーノードへの設定は完了したので、今度はPodについて考えます。次のようにIAMロールを定義したjsonファイルを作成します。


kube2iam-role.json

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<YOUR_ACCOUNT>:role/<NODE_INSTANCE_ROLE>"
},
"Action": "sts:AssumeRole"
}
]
}

次にjsonファイルからIAMロールを作成します。

$ aws iam create-role \

--role-name kube2iam-role \
--assume-role-policy-document file://kube2iam-role.json

S3のフルアクセス権限をIAMロールにアタッチします。

$ aws iam attach-role-policy \

--role-name kube2iam-role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess


DaemonSetのデプロイ

IAMロールの作成は完了したのでどのPodにIAMロールをつけるかを見つけて実際に付与するためのDaemonSetとその権限周りのリソースをデプロイします。


kube2iam.yaml

---

apiVersion: v1
kind: ServiceAccount
metadata:
name: kube2iam
namespace: kube-system
---
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube2iam
rules:
- apiGroups: [""]
resources: ["namespaces","pods"]
verbs: ["get","watch","list"]
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube2iam
subjects:
- kind: ServiceAccount
name: kube2iam
namespace: kube-system
roleRef:
kind: ClusterRole
name: kube2iam
apiGroup: rbac.authorization.k8s.io
kind: List
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube2iam
namespace: kube-system
labels:
app: kube2iam
spec:
selector:
matchLabels:
app: kube2iam
template:
metadata:
labels:
app: kube2iam
spec:
serviceAccountName: kube2iam
hostNetwork: true
containers:
- name: kube2iam
image: jtblin/kube2iam:latest
imagePullPolicy: Always
args:
- "--auto-discover-base-arn"
- "--iptables=true"
- "--host-ip=$(HOST_IP)"
- "--host-interface=eni+"
- "--verbose"
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
ports:
- containerPort: 8181
hostPort: 8181
name: http
securityContext:
privileged: true

これをデプロイすればkube2iamの設定は終わりです。

$ kubectl apply -f kube2iam.yaml


3. SecretからS3アクセス認証情報の設定

S3へのアクセス情報をSecretとして定義していきます。


Registy

Dockerレジストリの設定を行います。使用するS3バケットの情報をyamlファイルとして保存します。


registry-storage.yaml

s3:

bucket: sample-gitlab-registry
v4auth: true
region: ap-northeast-1

このyamlファイルからSecretを作成します。

$ kubectl create secret generic registry-storage \

--from-file=config=registry-storage.yaml


LFS, Artifacts, Uploads, Packages, Diffs, Pseudonymizer

LFS, Artifacts, Uploads, Packages, Diffs, Pseudonymizerに使うオブジェクトストレージの設定を行います。使用するS3バケットの情報をyamlファイルとして保存します。


rails-storage.yaml

provider: AWS

use_iam_profile: true
region: ap-northeast-1

このyamlファイルからSecretを作成します。

$ kubectl create secret generic rails-storage \

--from-file=connection=rails-storage.yaml


Backups

バックアップを行うための設定を行います。使用するS3バケットの情報をyamlファイルとして保存します。


storage.config

[default]

bucket_location = ap-northeast-1

このファイルからSecretを作成します。

$ kubectl create secret generic storage-config \

--from-file=config=storage.config


4. GitLab Helm Chartの編集およびデプロイ

S3にアクセス可能なオリジナルHelm Chartを作成しEKSにデプロイしていきます。


Helm Tillerのインストール

EKSでHelmを使うためのRBACを設定します。


tiller-rbac.yaml

---

apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system

このマニフェストファイルをデプロイします。

$ kubectl apply -f tiller-rbac.yaml

下記コマンドでHelm Tillerをインストールします。

$ helm init --service-account tiller


Helm Chartの作成

まずは公式のGitLab Helm Chartをダウンロードします。

$ helm fetch gitlab/gitlab --version 2.1.0

ダウンロードしたHelm Chartを解凍します。

$ tar -xvzf gitlab-2.1.0.tgz

次にgitlab/values.yaml を編集します。加筆修正箇所は下記となります。

key
value
備考

1
global.edition
ce

2
global.gitlabVersion
12.1.0
Helm Chartのバージョンに合わせる
https://gitlab.com/charts/gitlab/blob/master/CHANGELOG.md

3
global.hosts.domain
<YOUR_DOMAIN_NAME>
自分が所有するドメイン名

4
global.minio.enabled
false

5
global.appConfig.lfs.bucket
<RELEASE>-gitlab-lfs

6
global.appConfig.lfs.connection.secret
rails-storage

7
global.appConfig.lfs.connection.key
connection

8
global.appConfig.artifacts.bucket
<RELEASE>-gitlab-artifacts

9
global.appConfig.artifacts.connection.secret
rails-storage

10
global.appConfig.artifacts.connection.key
connection

11
global.appConfig.uploads.bucket
<RELEASE>-gitlab-uploads

12
global.appConfig.uploads.connection.secret
rails-storage

13
global.appConfig.uploads.connection.key
connection

14
global.appConfig.packages.bucket
<RELEASE>-gitlab-packages

15
global.appConfig.packages.connection.secret
rails-storage

16
global.appConfig.packages.connection.key
connection

17
global.appConfig.externalDiffs.enabled
true

18
global.appConfig.externalDiffs.bucket
<RELEASE>-gitlab-mr-diffs

19
global.appConfig.externalDiffs.connection.secret
rails-storage

20
global.appConfig.externalDiffs.connection.key
connection

21
global.appConfig.pseudonymizer.bucket
<RELEASE>-gitlab-pseudo

22
global.appConfig.pseudonymizer.connection.secret
rails-storage

23
global.appConfig.pseudonymizer.connection.key
connection

24
global.appConfig.backups.bucket
<RELEASE>-gitlab-backups

25
global.appConfig.backups.tmpBucket
<RELEASE>-gitlab-tmp

26
global.registry.bucket
<RELEASE>-gitlab-registry

27
certmanager-issuer.email
<YOUR_EMAIL_ADDRESS>
Let's encryptで用いるeメールアドレス

28
registry.annotations."iam.amazonaws.com/role"
kube2iam-role
iam.amazonaws.com/role: kube2iam-role
という形になる

29
registry.storage.secret
registry-storage

30
registry.storage.key
config

31
gitlab.unicorn.annotations."iam.amazonaws.com/role"
kube2iam-role

32
gitlab.sidekiq.annotations."iam.amazonaws.com/role"
kube2iam-role

33
gitlab.task-runner.annotations."iam.amazonaws.com/role"
kube2iam-role

34
gitlab.task-runner.backups.objectStorage.config.secret
storage-config

35
gitlab.task-runner.backups.objectStorage.config.key
config

編集したものをパッケージ化します。

$ helm package gitlab


アプリのデプロイ

新たなに生成されたHelm Chartを用いてデプロイします。

## installの場合

$ helm install --name <RELEASE> gitlab-2.1.0.tgz

## upgradeの場合
$ helm upgrade <RELEASE> gitlab-2.1.0.tgz

デプロイ後自動でCLBが作成されます。このDNS名を下記コマンドで確認してみます。

$ kubectl get ingress -o wide

NAME HOSTS ADDRESS PORTS AGE
cm-acme-http-solver-b8zjt registry.<YOUR_DOMAIN_NAME> XXXXXX.ap-northeast-1.elb.amazonaws.com 80 22m
cm-acme-http-solver-rbmm2 gitlab.<YOUR_DOMAIN_NAME> XXXXXX.ap-northeast-1.elb.amazonaws.com 80 22m
<RELEASE>-registry registry.<YOUR_DOMAIN_NAME> XXXXXX.ap-northeast-1.elb.amazonaws.com 80, 443 22m
<RELEASE>-unicorn gitlab.<YOUR_DOMAIN_NAME> XXXXXX.ap-northeast-1.elb.amazonaws.com 80, 443 22m

Route53等のCNAME設定を入れることでCLBに飛ばすようにしましょう。CNAMEにする理由は、リクエストホストがgitlab.<YOUR_DOMAIN_NAME>でないと内部のnginxがルーティングしてくれないからです。


疎通確認

GitLabにログインしてみます。

スクリーンショット 2019-08-13 16.55.27.png

初期パスワードは下記コマンドで確認できます。

$ kubectl get secret <RELEASE>-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode

試しにアイコン画像を変えてみます。

スクリーンショット 2019-08-13 17.03.52.png

AWSコンソールでS3を確認するとuploadsのバケットにきちんとアイコン画像がファイルとして入っているのが確認できます。

スクリーンショット 2019-08-13 17.06.48.png


まとめ

EKSにHelmでデプロイしたGitLabとS3を連携させる手順を紹介しました。

作成しなければならないS3バケットが多いこととSecretの作成が面倒なことが難点ですが、やはりminioよりS3を使ったほうがファイル管理は楽だと思います。

また、Gitリポジトリデータが増えていくとバックアップファイルもその分大きくなっていきます。S3を利用せずこれをリストアしようとなると、リストアを実行するPodに十分なディスク容量が与えられてないと失敗します。

以上のことからもS3を利用することをおすすめします。