AWS EKSをGitLabデプロイ環境として使う

先日AWS EKS（Elastic Container Service for Kubernetes）の[Global Availability発表](https://aws.amazon.com/jp/about-aws/whats-new/2018/06/amazon-elastic-container-service-for-kubernetes-eks-now-ga/)に続き、[GitLabが正式サポートする](https://about.gitlab.com/2018/06/06/eks-gitlab-integration)ことを発表しました。

さっそく試してみたいと思います！

![maximilian-weisbecker-121294-unsplash.jpg](https://qiita-image-store.s3.amazonaws.com/0/260796/4d57e308-a105-19b3-6bd7-884ea0ed00b3.jpeg)

今回やりたいことは：

* 既存のGitLabインスタンスで
* Ruby on Railsプロジェクトに
* AWS EKS クラスタを連携して
* Auto DevOpsのCIパイプラインを実行させる

## 始める前に

* [GitLabについて](https://about.gitlab.com/)
* [Kubernetesについて](https://kubernetes.io/)
* [AWS EKS](https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html)

## 事前準備（Mac OS）

https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html

* Python 2 version 2.7.9+ or Python 3 version 3.3+

```shell:
> python --version
Python 2.7.10
```

* [pip](https://pip.readthedocs.io/en/stable/installing/)

* [AWS CLI version 1.15.32以上](https://docs.aws.amazon.com/cli/latest/userguide/installing.html)

```shell:
> set -x PATH /Users/jb/Library/Python/2.7/bin $PATH
> aws --version
aws-cli/1.15.34 Python/2.7.10 Darwin/17.5.0 botocore/1.10.34
```

* [kubectl CLI v1.10以上](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-with-homebrew-on-macos)

```shell:
> kubectl version --short --client
Client Version: v1.10.2
```

* [heptio-authenticator-aws](https://github.com/heptio/authenticator)

```shell:
> curl -o heptio-authenticator-aws https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/bin/darwin/amd64/heptio-authenticator-aws
> chmod +x ./heptio-authenticator-aws
> mv heptio-authenticator-aws ~/bin/
> which heptio-authenticator-aws
/Users/jb/bin/heptio-authenticator-aws
```

## AWSでEKS clusterを作成

### AWSアカウントと環境変数の準備

今回はコマンドラインで完結させたいので、自分のAWSアカウント設定を用意しておきましょう（`~/.aws/config`などでもよし、環境変数でもよし）。

EKSはまだTokyoリージョンにリリースされていないので、`us-west-2`を使います。

```shell:
> set -x AWS_DEFAULT_REGION us-west-2
> echo $AWS_DEFAULT_REGION
us-west-2
```

また、省略しますが以下を事前に用意しましょう：

* SSH keypair
* EKS権限を持つIAM Role

```shell:
set -x EKS_WORKER_STACK_NAME noraneco-workers
set -x EKS_IAM_ROLE arn:aws:iam::315358830128:role/noraneco-eks

set -x EKS_CLUSTER_NAME noraneco-devops
set -x SECURITY_GROUP sg-25e4f147

set -x NODE_GROUP_NAME noraneco-workers-group
set -x NODE_AUTO_SCALING_GROUP_MIN_SIZE 1
set -x NODE_AUTO_SCALING_GROUP_MAX_SIZE 3
set -x NODE_INSTANCE_TYPE t2.medium
set -x NODE_IMAGE_ID ami-73a6e20b
set -x EKS_KEY_NAME noraneco-sshkey

set -x VPC_ID vpc-070b0065
set -x SUBNETS \'subnet-6f184c29,subnet-9da3abff,subnet-5b53792f\'
set -x EKS_SUBNETS subnet-6f184c29,subnet-9da3abff,subnet-5b53792f
```


### クラスタを作成

```shell:
> aws eks create-cluster --name ${EKS_CLUSTER_NAME} --role-arn ${EKS_IAM_ROLE} --resources-vpc-config subnetIds=${EKS_SUBNETS},securityGroupIds=${SECURITY_GROUP}
{
    "cluster": {
        "status": "CREATING",
        "name": "noraneco-devops",
        "certificateAuthority": {},
        "roleArn": "arn:aws:iam::315358830128:role/noraneco-eks",
        "resourcesVpcConfig": {
            "subnetIds": [
                "subnet-6f184c29",
                "subnet-9da3abff",
                "subnet-5b53792f"
            ],
            "vpcId": "vpc-070b0065",
            "securityGroupIds": [
                "sg-25e4f147"
            ]
        },
        "version": "1.10",
        "arn": "arn:aws:eks:us-west-2:315358830128:cluster/noraneco-devops",
        "createdAt": 1528758865.456
    }
}

> aws eks list-clusters
{
    "clusters": [
        "noraneco-devops"
    ]
}
```

5分ほどかかります。以下のコマンドでステータスが`ACTIVE`になれば完了です。

```shell:
> aws eks describe-cluster --name ${EKS_CLUSTER_NAME}
{
    "cluster": {
        "status": "ACTIVE",
        "endpoint": "https://0FD98C1B9E833B46110E1E9272C71AD0.yl4.us-west-2.eks.amazonaws.com",
        "name": "noraneco-devops",
        "certificateAuthority": {
            "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNE1EWXhNakF5TURVME1sb1hEVEk0TURZd09UQXlNRFUwTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTEhnCnFqSm5EL0pZQVlWazRjS1ZGYUxpRWZMem9XWjFKSkxEbnNFckx4TEtlM1pCSUJqNUpXMGpvZjJHOSt2TnJ6K3gKeXM5ck1lL1c2WnlMakJtbVUxcFFPWlhJa1hRZDhTNTlLOXU2MVRJWkRHY0xneG1IeXp6TzVlWXBoQ2xtYUlQYQpSZWpISm9MRWtKS2FzTmhKRG94Mk0xVVRUSjVPTTZ3VjdaY1pOVVFFcU1rdnQvWHlLZFRxQ2RnM0ZNMm1Qam1UClV6T3plcFU0d1FoMXJURGtoUnlaN1hqREpiZjYvd1lZRitzRmo0VlBTNHpMM3psd2xzYnhpVlRMQS9ld01vQmwKVU5UU0FNbkliTW1XU3I5Mit5MGFyMGVUVTk1eXVNbXRYbEx0VTh5b1JXMUlkc1VrVGM0R2x4V1M4S0FmMklRYQpER05rR0JkT3pqZSttd3hBSnI4Q0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJdmNqZ0FzL2o4eVJxeVh2bU5DNGRQVzQwRTEKWVZ0RGxvZTQzd1BnLzlneXp3WldDWHpFU1hTMURiempEbWZmTlpvek0wNVU4ZlVaeGcwZTd6QjY5VEhOd2NlaApQN1RVQ2g1WmFNbjBla21HcHcyZ3Naa01GTEVDNkFXMUU4TTZBTTlUWDVqMTBpek5LTVl1d2thUFVBeFQ1dXZICnhocEV1QkI5Q1VMaXBLb0FMS01xTmEzWnpJMU4zVEZlV3RldHkrb0pWWVp5emJQdHAyWHRnTDRVYlhxQ3FhUU4KT0JoV1JGMWhTUTQ2SXVhNStpMEFQSU9VckdYOW4zT2ZWUUtBK2tHb1g2TG1kV0pTdk93dmdqZDZOV3VGTUd4dApoNG9Zb0dMOXdGYWRMcjZuYjkzc0p5cHBnYzlLZHBMZldVTUVlMlFSb3Awd3l1bjNtM1hGZ0c5YW9jYz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
        },
        "roleArn": "arn:aws:iam::315358830128:role/noraneco-eks",
        "resourcesVpcConfig": {
            "subnetIds": [
                "subnet-6f184c29",
                "subnet-9da3abff",
                "subnet-5b53792f"
            ],
            "vpcId": "vpc-070b0065",
            "securityGroupIds": [
                "sg-25e4f147"
            ]
        },
        "version": "1.10",
        "arn": "arn:aws:eks:us-west-2:315358830128:cluster/noraneco-devops",
        "createdAt": 1528768731.985
    }
}
```

### ノードを作成

Cloudformationで気軽にノードのスタックが作れますので、それを採用します。

```shell:
> aws cloudformation create-stack \
    --stack-name ${EKS_WORKER_STACK_NAME} \
    --template-body https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/amazon-eks-nodegroup.yaml \
    --parameters \
        ParameterKey=ClusterName,ParameterValue=${EKS_CLUSTER_NAME} \
        ParameterKey=ClusterControlPlaneSecurityGroup,ParameterValue=${SECURITY_GROUP} \
        ParameterKey=NodeGroupName,ParameterValue=${NODE_GROUP_NAME} \
        ParameterKey=NodeAutoScalingGroupMinSize,ParameterValue=${NODE_AUTO_SCALING_GROUP_MIN_SIZE} \
        ParameterKey=NodeAutoScalingGroupMaxSize,ParameterValue=${NODE_AUTO_SCALING_GROUP_MAX_SIZE} \
        ParameterKey=NodeInstanceType,ParameterValue=${NODE_INSTANCE_TYPE} \
        ParameterKey=NodeImageId,ParameterValue=${NODE_IMAGE_ID} \
        ParameterKey=KeyName,ParameterValue=${EKS_KEY_NAME} \
        ParameterKey=VpcId,ParameterValue=${VPC_ID} \
        ParameterKey=Subnets,ParameterValue=${SUBNETS} \
    --capabilities CAPABILITY_IAM

{
    "StackId": "arn:aws:cloudformation:us-west-2:315358830128:stack/noraneco-workers/1badad40-6de7-11e8-b750-503ac931688d"
}
```

**メモ**: インスタンスはt2.small では不安定な模様、t2.medium以上を推奨します。

10分程度かかります、コーヒーを作ります。
ちなみに以下のコマンドで終わるタイミングで教えてくれます（スピーカーのボリュームを最大にしましょう）。

```shell:
aws cloudformation wait stack-create-complete --stack-name $EKS_WORKER_STACK_NAME ; say "finished"
```

終わったあとに`NodeInstanceRole`の値を取得します。ノードをクラスタに参加させるために必要になります。

```shell:
> aws cloudformation describe-stacks \
                                       --stack-name $EKS_WORKER_STACK_NAME \
                                       --query 'Stacks[0].Outputs[0].OutputValue' \
                                       | sed -E 's/.(.*)./\1/'
arn:aws:iam::315358830128:role/noraneco-workers-NodeInstanceRole-CSJHW1MNLK1Y
```

### kubectlでクラスタに接続

好きなフォルダ（一般的には`~/.kube/`）に`kubeconfig`を作成します。

クラスタのサーバURL、CA証明書、EKSインスタンス名を書きまえます。

```yaml:
apiVersion: v1
clusters:
- cluster:
    server: https://361767AA37E2DAEB2C7DB16150121B9A.sk1.us-west-2.eks.amazonaws.com
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNE1EWXdPREE0TURFeU4xb1hEVEk0TURZd05UQTRNREV5TjFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBT3NaCjB2bUtCOXJKZHZUSm82WjREY1BydzdoWUxNOVdNbHFHeDI0SWNFWUhxSUszdlVQd2tST2UvMUJSY3Vud01kUzMKMnMwSmpNbjVYbW1DUG13YTFpL0NjQU9Ma1U1aVRXc2k3YmJZM0FBc1hTbVg3bXJYaW1ZN01JY204a2FsdE9OVQpSdHB4dGJrckJYU0tiM0pxeXB2SlBWTkVBcWpMMksvV0c3ZzFJT0RIb1lSNnF5SGpsNHYwRjhDVTJybitYQzRpCjdBalZXL1ZpVlNpYXJEMUl2Qmh0MHl3TlRmM25NWE5TR2t6TkpwbjYzOXlaYTgrM3ZOQVdmZlYvTktxTklYRHkKN2d4RHJUVzY2dmJvam1Wdm91b0o3eXYzOCsrN3BKaHhmUEJhU0ZZenhpeklObC8ySjBXcFZ2UXJIRFMxL2FjSgo2NWZNYXRlRDUvZ0RYZVBSak84Q0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFFU3p3ZDZkSnYwSllDRlUzeG1aSjZ3QmFwTWQKVEx3aG0xbTlGNDJwYmpZUDJxZ2w0Z0NLMHZZNXE2UlplQ3Z2R1l1T3R4M0dUZEdTSjVGeS8yNkt3a0lZOTlmRQpIT2Y0MzdlMDE5QWs4bHE3WTQ4VEZBajVLejd1YmpUTzlQYVNJbDJJZ2xpamkvV0t6NUhHd1ZVWmV2VjBPQWk4CjlJM2w4NG9kd1BsRXl0eWdKRE81M2JxeXBuK3BaZkNHOXBMcmdmc2FCS1YyTGVZZkRKQk1MUFFleWM1d1hMdlEKTys0cjl5c1lYa05jZHhMeW5GTnNkc0k4bzQxaTlVSWlPYS9QZUl4eWpxMG5EcURrWXVvcEhiWWFuckFJUlV2UwpLd3ZLYlEwanhQdlZud09zOWRxVDRkTE9nMlFGeFJnMW9XRlhrYWNKRm9ORXBtYTlLR0hCdXp4aEh3dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: aws
  name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      command: heptio-authenticator-aws
      args:
        - "token"
        - "-i"
        - "noraneco-devops"
```

このファイルを`kubectl`の設定ファイルとして登録します。

```shell:
> set -x KUBECONFIG ./kubeconfig
```

これで、クラスタが見れるようになります。

```shell:
> kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   3d
```

### ノードをクラスタに参加させる

この時点でクラスタにはノーだはない状態です。

```shell:
> kubectl get nodes
No resources found.
```

AWS authenticator configuration mapファイルをダウンロードし、先程取得した`NodeInstanceRole`を入れ込みます。

```shell:
> curl -O https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/aws-auth-cm.yaml
```

```yaml:
apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: arn:aws:iam::315358830128:role/noraneco-workers-NodeInstanceRole-CSJHW1MNLK1Y
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
```

`kubectl`でConfigMapを適用します。

```shell:
> kubectl apply -f aws-auth-cm.yaml
configmap "aws-auth" created
```

数秒後ノードがクラスタに参加した状態になります。

```shell:
> kubectl get nodes
NAME                                         STATUS    ROLES     AGE       VERSION
ip-172-31-13-93.us-west-2.compute.internal    Ready     <none>    57s       v1.10.3
ip-172-31-16-186.us-west-2.compute.internal   Ready     <none>    59s       v1.10.3
ip-172-31-34-141.us-west-2.compute.internal   Ready     <none>    1m        v1.10.3
```

コマンドラインの作業はこれで（ほぼ）終了です。
EKSの感想は。。。手作業が多い！！！
もう少し自動化してくれても良い気持ちですが、まぁshell化なりterraform化なり簡単にできるので良しとしますか。

![2017-11-19 09.30.53.jpg](https://qiita-image-store.s3.amazonaws.com/0/260796/10a46801-fbb5-e0bd-e565-114b00482380.jpeg)

GitLabで必要となる情報を取得しておき、CLIをお休みにします。

* シークレット名（あとのコマンドで必要）

```shell:
> kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-mghhh   kubernetes.io/service-account-token   3         27m
```

* token

```shell:
> kubectl get secret default-token-mghhh -o jsonpath="{['data']['token']}" | base64 -D
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tbWdoaGgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjQ0NTUxOWM4LTZkZTUtMTFlOC1hN2ExLTA2MzcxY2VmMDg1OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.GKkBUzbm7SoSFs1DHmTavTw67jlD-XvYsb-dH4VD0vnYoF0HueCvcuYdKRn8-_-kHopmAQrHVWvMPdxxQKnWK0gDDZzLm_QQxc2kiEURiHxrYV2q3JP0mZgROqhoRkTI2hLEX7K6NNkNrWcAVwFwfqh_JS0uWuOqzNjWEhTs47RtUgzT14OH2nnlmotBC9YecTx5wVBnbQxf5EMdaT3dTiMQcUm99y5QDM_reUIUcc2eqEBnlX-3aPSupkhprHgLarnBEDkzkb2zPnnvPiQNFo7VjxkBKwtGCFY1gswveMG17J7Dwue-CqRDKIaAOd1zoXD0nagG4FWYa-wQMK_hCw
```

* CA Certificate

```shell:
> kubectl get secret default-token-mghhh -o jsonpath="{['data']['ca\.crt']}" | base64 -D
-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTE4MDYxMjAyMDU0MloXDTI4MDYwOTAyMDU0MlowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALHg
qjJnD/JYAYVk4cKVFaLiEfLzoWZ1JJLDnsErLxLKe3ZBIBj5JW0jof2G9+vNrz+x
ys9rMe/W6ZyLjBmmU1pQOZXIkXQd8S59K9u61TIZDGcLgxmHyzzO5eYphClmaIPa
RejHJoLEkJKasNhJDox2M1UTTJ5OM6wV7ZcZNUQEqMkvt/XyKdTqCdg3FM2mPjmT
UzOzepU4wQh1rTDkhRyZ7XjDJbf6/wYYF+sFj4VPS4zL3zlwlsbxiVTLA/ewMoBl
UNTSAMnIbMmWSr92+y0ar0eTU95yuMmtXlLtU8yoRW1IdsUkTc4GlxWS8KAf2IQa
DGNkGBdOzje+mwxAJr8CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIvcjgAs/j8yRqyXvmNC4dPW40E1
YVtDloe43wPg/9gyzwZWCXzESXS1DbzjDmffNZozM05U8fUZxg0e7zB69THNwceh
P7TUCh5ZaMn0ekmGpw2gsZkMFLEC6AW1E8M6AM9TX5j10izNKMYuwkaPUAxT5uvH
xhpEuBB9CULipKoALKMqNa3ZzI1N3TFeWtety+oJVYZyzbPtp2XtgL4UbXqCqaQN
OBhWRF1hSQ46Iua5+i0APIOUrGX9n3OfVQKA+kGoX6LmdWJSvOwvgjd6NWuFMGxt
h4oYoGL9wFadLr6nb93sJyppgc9KdpLfWUMEe2QRop0wyun3m3XFgG9aocc=
-----END CERTIFICATE-----
```

## GitLabでプロジェクトにクラスタを連携

参照： https://docs.gitlab.com/ee/user/project/clusters/eks_and_gitlab/#create-a-default-storage-class

### Ruby on Railsプロジェクトを作成

`New Project`、`Create from Template`の`Ruby on Rails`を選択し新規プロジェクトを作成します。

<img width="661" alt="Screen Shot 2018-06-12 at 20.58.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/260796/83817a36-8ef7-e343-1839-82450e712301.png">

### EKSクラスタを連携

作成したプロジェクトを開き、左メニューから`CI/CD` > `Kubernetes` > `Add an existing cluster`を選択し、必要な情報を記入し登録します。

<img width="660" alt="Screen Shot 2018-06-11 at 20.38.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/260796/4feb54f6-9a9c-1414-b796-5cf4e7fe6f8e.png">

Auto DevOpsを利用しないなら、ここで終了です！

## Auto DevOps実践

### Role Based-Access Control (RBAC)を無効化

現時点でAuto DevOpsは[Kubernetes RBACの対応](https://gitlab.com/groups/gitlab-org/-/epics/136)は終わっていません。
セキュリティの観点では望ましくないですが、デモのためにRBACを無効化する必要があります。

```shell:
> kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts
clusterrolebinding.rbac.authorization.k8s.io "permissive-binding" created
```

### Tiller/Ingress/Prometheusサービスをデプロイ

GitLabのkubernetes画面にて以下のサービスをクラスタにデプロイします。

* Tiller
* Ingress
* Prometheus

**メモ**: うまくいかないときがあります。そのとき以下のコマンドで``を削除してGUIから再度インストールをしてください（以下はPrometheusが失敗したときの対処）。

```shell:
> kubectl get configmaps --all-namespaces
NAMESPACE             NAME                                      DATA      AGE
gitlab-managed-apps   ingress-controller-leader-nginx           0         13m
gitlab-managed-apps   ingress-nginx-ingress-controller          1         15m
gitlab-managed-apps   ingress.v1                                1         15m
gitlab-managed-apps   values-content-configuration-ingress      1         15m
gitlab-managed-apps   values-content-configuration-prometheus   1         11m
kube-system           aws-auth                                  1         33m
kube-system           kube-dns                                  0         42m
kube-system           kube-proxy                                1         42m

> kubectl delete configmap values-content-configuration-prometheus -n gitlab-managed-apps
configmap "values-content-configuration-prometheus" deleted
```

### 任意のドメインにDNSレコードを登録

Ingressのサービスで外部からアクセス可能なエンドポイントが用意されます。
これを取得してRoute53などでドメインのDNSレコードに登録します。

> EKSの場合は、IPアドレスではなくCNAMEが返ってきます。

```shell:
> kubectl describe service ingress-nginx-ingress-controller -n gitlab-managed-apps
Name:                     ingress-nginx-ingress-controller
Namespace:                gitlab-managed-apps
Labels:                   app=nginx-ingress
                          chart=nginx-ingress-0.20.3
                          component=controller
                          heritage=Tiller
                          release=ingress
Annotations:              <none>
Selector:                 app=nginx-ingress,component=controller,release=ingress
Type:                     LoadBalancer
IP:                       10.100.13.19
LoadBalancer Ingress:     acf5c578b6ded11e8a7a106371cef085-133012040.us-west-2.elb.amazonaws.com
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  31580/TCP
Endpoints:                172.31.9.218:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  30851/TCP
Endpoints:                172.31.9.218:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  EnsuringLoadBalancer  9m    service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   9m    service-controller  Ensured load balancer
```

### default Storage Classを作成

EKSにはStorage Classはデフォルトで用意されませんので手動で作成します。

参考： https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html

`gp2-storage-class.yaml`ファイルを作成します。

```yaml:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp2
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
mountOptions:
  - debug
```

そして、クラスタに適用します。

```shell:
> kubectl create -f gp2-storage-class.yaml

storageclass.storage.k8s.io "gp2" created

> kubectl get storageclass
NAME      PROVISIONER             AGE
gp2       kubernetes.io/aws-ebs   41s
```

念のため、デフォルトストレージクラスとして登録します。

```shell:
> kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
storageclass.storage.k8s.io "gp2" patched

> kubectl get storageclass
NAME            PROVISIONER             AGE
gp2 (default)   kubernetes.io/aws-ebs   1m
```

### Auto DevOps機能を有効化

GitLabのプロジェクト画面に戻り、左メニューの`Settings` > `CI/CD` > `Auto DevOps (Beta)`を開き、`Enable Auto DevOps`を選択し、デプロイ用のドメインを記入して`Save changes`で有効にします。

<img width="661" alt="Screen Shot 2018-06-12 at 21.33.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/260796/507a9913-5ba7-ca98-f8e3-9d093a5e1b0c.png">

### CI Pipelineを実行

左メニューの`CI/CD` > `Pipelines`から`Run Pipeline`を選択し実行します。

ここまで無事に辿り着けば、以下のようにビルド・テスト・本番デプロイ・性能試験が実行されます。

<img width="661" alt="Screen Shot 2018-06-12 at 11.51.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/260796/05c0f95a-c362-7498-21c8-a7c08c14555e.png">

もう一度コーヒーを淹れます。

さらに`CI/CD` > `Environments`の画面からproduction環境にデプロイされたアプリケーションの情報が確認できます。

<img width="661" alt="Screen Shot 2018-06-12 at 21.42.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/260796/376ee358-f6ea-88c6-8ccf-b09f62cbad5b.png">


右側にあるボタンは*ブラウザでアプリケーションを開く*、*アプリケーションコンテナにssh接続*になっています。

複数環境を運用する場合一目でどのバージョンなのかが分かり、稼動状況やアプリケーションログが確認できて非常に便利です。

実験終了です！

感想としては、Auto DevOpsは相変わらずすごいですね！
GUIでクラスタを連携する際にいくつか不安定（[バグ？](https://gitlab.com/gitlab-org/gitlab-ce/issues/45939)）な箇所がありましたが改善されていくでしょう。
構築と設定の作業をプロジェクトごとにやっていくのが辛いので全自動化したいですね。