EKSWorkshopを途中までやってみた2

前回までの進捗はこちら

今回は ネットワークポリシーを使用してクラスターをセキュアにするところまで

Step16

CodePipelineを使用したCI/CD

workshop:~/environment $ kubectl describe configmap -n kube-system aws-auth
Name:         aws-auth
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>

Data
====
mapRoles:
----
- rolearn: arn:aws:iam::0123456789:role/EksWorkshopCodeBuildKubectlRole
  username: build
  groups:
    - system:masters
  • リポジトリをフォークする
  • Githubアクセストークンを発行する(repoの権限だけ与えればOK)
  • CloudFormationでCodePipelineをセットアップする(Lauchボタンから実行するだけ)
  • デプロイが完了するのを待つ
  • external ipを取得してアクセスする
  • GitHubで内容を変更してコミットする(自動的にパイプラインが実行される)
  • デプロイが完了したら再度アクセスする(内容が更新されていることがわかる)
  • デプロイしたものを掃除する(Githubのアクセストークンも忘れずに)

Step17

Jenkinsをデプロイする

  • helmを使ってjenkinsをデプロイ
  • podが起動するのを待つ
workshop:~/environment $ kubectl get pods -w
NAME                            READY   STATUS     RESTARTS   AGE
cicd-jenkins-54dd8cfdb4-h2spv   0/1     Init:0/1   0          33s
cicd-jenkins-54dd8cfdb4-h2spv   0/1   Init:0/1   0     42s
cicd-jenkins-54dd8cfdb4-h2spv   0/1   PodInitializing   0     50s
cicd-jenkins-54dd8cfdb4-h2spv   0/1   Running   0     53s
cicd-jenkins-54dd8cfdb4-h2spv   1/1   Running   0     2m
  • external ipを取得してアクセスする
  • adminとコマンドを実行して取得したパスワードを用いてログイン
  • 少し触ってみる
  • デプロイしたものを掃除する

Step18

X-RAYを使用したトレーシング

  • 既存のロールにポリシーをアタッチする(arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess)
  • X-RAYのDaemonSetをデプロイする(稼働するまで待つ、今回はNodeの数を2個に減らしている)
workshop:~/environment $ kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
xray-daemon-62hjv   1/1     Running   0          80s
xray-daemon-hnpsh   1/1     Running   0          80s

workshop:~/environment $ kubectl logs -l app=xray-daemon
2019-10-02T00:29:02Z [Info] Initializing AWS X-Ray daemon 3.0.0
2019-10-02T00:29:02Z [Info] Using buffer memory limit of 76 MB
2019-10-02T00:29:02Z [Info] 1216 segment buffers allocated
2019-10-02T00:29:02Z [Info] Using region: ap-northeast-1
2019-10-02T00:29:02Z [Info] Starting proxy http server on 127.0.0.1:2000
2019-10-02T00:29:02Z [Info] Initializing AWS X-Ray daemon 3.0.0
2019-10-02T00:29:02Z [Info] Using buffer memory limit of 76 MB
2019-10-02T00:29:02Z [Info] 1216 segment buffers allocated
2019-10-02T00:29:02Z [Info] Using region: ap-northeast-1
2019-10-02T00:29:02Z [Info] Starting proxy http server on 127.0.0.1:2000
  • サンプルのマイクロサービス(frontend/backend)をデプロイする(稼働するまで待つ)
workshop:~/environment $ kubectl get pod 
NAME                                      READY   STATUS    RESTARTS   AGE
x-ray-sample-back-k8s-7668487768-6pncb    1/1     Running   0          56s
x-ray-sample-back-k8s-7668487768-c9zw7    1/1     Running   0          56s
x-ray-sample-back-k8s-7668487768-nn26x    1/1     Running   0          56s
x-ray-sample-front-k8s-7c6568455b-54xqw   1/1     Running   0          64s
x-ray-sample-front-k8s-7c6568455b-d7prm   1/1     Running   0          64s
x-ray-sample-front-k8s-7c6568455b-v9hsw   1/1     Running   0          64s
xray-daemon-62hjv                         1/1     Running   0          4m17s
xray-daemon-hnpsh                         1/1     Running   0          4m17s
  • frontendのexternal ipを取得してアクセスする
  • X-RAYの画面でリクエストのトレーシングを見る
  • デプロイしたものを掃除する

Step19

Argoを使用したバッチ処理
Argoはワークフローエンジンらしい
(使ったことないので初だが、Airflowとかに近いイメージを持っておけば良さそう?)

  • ジョブを作成し、正常に完了するまで待つ
  • 実行完了したらログを見る
workshop:~/environment $ kubectl logs -l job-name=whalesay

     \
      \
                    ##        .
              ## ## ##       ==
           ## ## ## ##      ===
       /""""""""""""""""___/ ===
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
       \______ o          __/
        \    \        __/
          \____\______/
  • Argo CLIをおとしてくる
  • Argoをデプロイする
  • admin権限をバインドする
  • アーティファクトようにS3バケットを作成する
  • コントローラーのConfigMapを編集する(S3の指定を行う)
  • S3への読み書き権限をインスタンスロールに付与して検証する
  • バッチのワークフローを作成して完了を待つ
Name:                whalesay-6jn4w
Namespace:           default
ServiceAccount:      default
Status:              Succeeded
Created:             Wed Oct 02 00:55:04 +0000 (16 seconds ago)
Started:             Wed Oct 02 00:55:04 +0000 (16 seconds ago)
Finished:            Wed Oct 02 00:55:20 +0000 (now)
Duration:            16 seconds

STEP               PODNAME         DURATION  MESSAGE
 ✔ whalesay-6jn4w  whalesay-6jn4w  16s      
  • 実行完了したらログを見る
workshop:~/environment $ argo logs whalesay-6jn4w
 ___________________________
< This is an Argo Workflow! >
 ---------------------------
    \
     \
      \
                    ##        .
              ## ## ##       ==
           ## ## ## ##      ===
       /""""""""""""""""___/ ===
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
       \______ o          __/
        \    \        __/
          \____\______/
  • 高度なバッチのワークフローを作成して完了を待つ
workshop:~/environment $ argo logs whalesay-6jn4w
 ___________________________
Name:                teardrop-r4pwz
Namespace:           default
ServiceAccount:      default
Status:              Succeeded
Created:             Wed Oct 02 00:58:36 +0000 (1 minute ago)
Started:             Wed Oct 02 00:58:36 +0000 (1 minute ago)
Finished:            Wed Oct 02 00:59:38 +0000 (now)
Duration:            1 minute 2 seconds

STEP               PODNAME                    DURATION  MESSAGE
 ✔ teardrop-r4pwz
 ├-✔ create-chain  teardrop-r4pwz-3237607044  7s
 ├-✔ Alpha         teardrop-r4pwz-3820296496  7s
 ├-✔ Bravo         teardrop-r4pwz-2282498488  7s
 ├-✔ Charlie       teardrop-r4pwz-4159768078  9s
 ├-✔ Delta         teardrop-r4pwz-3891602682  7s
 ├-✔ Echo          teardrop-r4pwz-197422989   13s
 ├-✔ Foxtrot       teardrop-r4pwz-3338295236  26s
 ├-✔ Golf          teardrop-r4pwz-3978399692  12s
 └-✔ Hotel         teardrop-r4pwz-2842417934  7s
  • proxy経由でアクセスして実行結果を見る
  • デプロイしたものを掃除する(InstanceRoleにputしたpolicyも忘れずに)

Step20

Kubeflowを使用した機械学習(今回は興味がないのでスキップ)

Step21

ProjectedServiceAccountTokenを使用したサービスアカウントのIAMロール
コンテナにIAMRoleの権限を渡して実行できるようにする(めちゃくちゃ嬉しい)

  • OpenID Conncet ProviderのURLを取得する
  • OIDC ID Providerを作成する(IAMのIDプロバイダーからも確認できる)
workshop:~/environment $ eksctl utils associate-iam-oidc-provider --name eksworkshop-eksctl --approve
[ℹ]  using region ap-northeast-1
[ℹ]  will create IAM Open ID Connect provider for cluster "eksworkshop-eksctl" in "ap-northeast-1"
[✔]  created IAM Open ID Connect provider for cluster "eksworkshop-eksctl" in "ap-northeast-1"
  • サービスアカウントのIAMロールを作成する
workshop:~/environment $ eksctl create iamserviceaccount --name iam-test --namespace default --cluster eksworkshop-eksctl --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --approve --override-existing-serviceaccounts
[ℹ]  using region ap-northeast-1
[ℹ]  1 iamserviceaccount (default/iam-test) was included (based on the include/exclude rules)
[!]  metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set
[ℹ]  1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "default/iam-test", create serviceaccount "default/iam-test" } }
[ℹ]  building iamserviceaccount stack "eksctl-eksworkshop-eksctl-addon-iamserviceaccount-default-iam-test"
[ℹ]  deploying stack "eksctl-eksworkshop-eksctl-addon-iamserviceaccount-default-iam-test"
[ℹ]  created serviceaccount "default/iam-test"
  • サービスアカウントが存在することを確認する
workshop:~/environment $ kubectl get sa
NAME       SECRETS   AGE
default    1         128m
iam-test   1         68s
  • IAMRoleが紐付いていることを確認する
workshop:~/environment $ kubectl describe sa iam-test
Name:                iam-test
Namespace:           default
Labels:              <none>
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::0123456789:role/eksctl-eksworkshop-eksctl-addon-iamserviceac-Role1-KGQWJMXKZPGM
Image pull secrets:  <none>
Mountable secrets:   iam-test-token-d2d5z
Tokens:              iam-test-token-d2d5z
Events:              <none>
  • podをデプロイする(specでserviceAccountNameを指定している)
workshop:~/environment $ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
eks-iam-test-7fb8c5ffb8-p59z2   1/1     Running   0          36s
  • [コンテナ内]でassume roleする
root@eks-iam-test-7fb8c5ffb8-p59z2:/# aws sts assume-role-with-web-identity \
> --role-arn $AWS_ROLE_ARN \
> --role-session-name mh9test \
> --web-identity-token file://$AWS_WEB_IDENTITY_TOKEN_FILE \
> --duration-seconds 1000
{
    "Credentials": {
        "AccessKeyId": "####################",
        "Expiration": "2019-10-02T01:51:46Z",
        "SessionToken": "######################################################",
        "SecretAccessKey": "#############################################"
    },
    "Audience": "sts.amazonaws.com",
    "AssumedRoleUser": {
        "Arn": "arn:aws:sts::0123456789:assumed-role/eksctl-eksworkshop-eksctl-addon-iamserviceac-Role1-KGQWJMXKZPGM/mh9test",
        "AssumedRoleId": "#######################:mh9test"
    },
    "Provider": "arn:aws:iam::0123456789:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/###############################",
    "SubjectFromWebIdentityToken": "system:serviceaccount:default:iam-test"
}
  • [コンテナ内]s3コマンドの発行(権限あり)
root@eks-iam-test-7fb8c5ffb8-p59z2:/# aws s3 ls
2019-10-02 01:37:01 eksworkshop-test-bucket // テストの為に作成した(Bucketが何も存在しなかったので)
  • [コンテナ内]ec2コマンドの発行(権限なし)
root@eks-iam-test-7fb8c5ffb8-p59z2:/# aws ec2 describe-instances --region ap-northeast-1
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
  • デプロイしたものを掃除する

Step22

WEAVE FLUXを使用したGitOps

  • S3にバケットを作成し、IAMRoleを作成する
  • Githubでリポジトリとアクセストークンを発行する(repoの権限だけ与えればOK)
  • FLUX CRDをデプロイする
  • レポジトリを追加(charts.fluxcd.io)
  • FLUXをデプロイする
workshop:~/environment $ kubectl get pods -n flux 
NAME                                 READY   STATUS    RESTARTS   AGE
flux-745c9cf59c-r25c2                1/1     Running   0          26s
flux-helm-operator-d58956875-5kj2p   1/1     Running   0          26s
flux-memcached-64886c48fb-rlmd9      1/1     Running   0          26s
  • fluxctlをおとしてくる
  • 提供されたSSH鍵を先程作成したリポジトリのデプロイキーとして追加する
  • CloudFormationでDockerイメージを作成するCodePipelineを作成する(Launchボタン押すだけ)
  • CloudFormationが作成完了すると同時にCodePipelineを確認すると失敗していることがわかる(RepoにREADMEしか置いてないため)
  • 自分のリポジトリ/サンプルのファイルを落としてcommitしてpush
  • 自分のリポジトリを落としてマニフェストをcommitしてpush
  • external ipでアクセスする
  • コードを修正して再度pushする(pipelineが実行されるのと、fluxでリリースがされているのを確認する)
  • 更新されたサイトが不評らしいのでk8s-configのHEADをrevertしてpushする
  • helmのnginx-chartをデプロイする
  • デプロイしたものを掃除する

Step23

ネットワークポリシーを使用してクラスターをセキュアにする

  • CALICOをデプロイしてDaemonSetがREADYになるのを待つ(Nodeは2つなので2でOK)
workshop:~/environment $ kubectl get daemonset calico-node --namespace=kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
calico-node   2         2         2       2            2           <none>          9m7s
  • 必要なリソースを落としてくる
  • 名前空間を作成する(namespace: stars)
  • 管理用のUIのリソース(名前空間/コントローラ/サービス)を作成する(namespace: management-ui)
  • Frontend/Backendのリソースを作成する(namespace: stars)
  • クライアントのリソース(名前空間/コントローラ/サービス)を作成する(namespace: client)
  • それぞれの名前空間が存在することを確認する
workshop:~/environment/calico_resources $ kubectl get pods --all-namespaces
NAMESPACE       NAME                                                  READY   STATUS    RESTARTS   AGE
client          client-xx7dv                                          1/1     Running   0          40s
kube-system     aws-node-9tzjm                                        1/1     Running   0          5h55m
kube-system     aws-node-w7dl6                                        1/1     Running   0          5h55m
kube-system     calico-node-8ds5q                                     1/1     Running   0          21m
kube-system     calico-node-8tr9j                                     1/1     Running   0          21m
kube-system     calico-typha-8599cbd6c-wjj7s                          1/1     Running   0          21m
kube-system     calico-typha-horizontal-autoscaler-65464c48bc-qcprl   1/1     Running   0          21m
kube-system     coredns-97bc697d6-p8npm                               1/1     Running   0          6h2m
kube-system     coredns-97bc697d6-tbf5q                               1/1     Running   0          6h2m
kube-system     kube-proxy-nx97l                                      1/1     Running   0          5h55m
kube-system     kube-proxy-z6kmh                                      1/1     Running   0          5h55m
kube-system     kubernetes-dashboard-57df4db6b-jqplm                  1/1     Running   0          5h46m
kube-system     tiller-deploy-5d6cc99fc-5lxcc                         1/1     Running   0          5h11m
management-ui   management-ui-4t9kj                                   1/1     Running   0          9m13s
stars           backend-qq4b2                                         1/1     Running   0          71s
stars           frontend-6d8h4                                        1/1     Running   0          69s
  • 管理UIにexternal ipを使用してアクセスする
    全てのポッド間の通信が出来ていることを確認する
  • starsとclientの名前空間で全てのアクセスをDenyにする
  • UI上で全てのポッドに対してアクセスができなくなったことを確認する(もちろんUIからも)
  • management-uiからの通信を許可する
workshop:~/environment/calico_resources $ kubectl describe pod management-ui-4t9kj -n management-ui
Name:               management-ui-4t9kj
Namespace:          management-ui
Priority:           0
PriorityClassName:  <none>
Node:               ip-192-168-3-16.ap-northeast-1.compute.internal/192.168.3.16
Start Time:         Wed, 02 Oct 2019 05:16:12 +0000
Labels:             role=management-ui

kind: NetworkPolicy
apiVersion: extensions/v1beta1 
metadata:
  namespace: stars
  name: allow-ui 
spec:
  podSelector:
    matchLabels: {}
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              role: management-ui 

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: client
  name: allow-ui
spec:
  podSelector:
    matchLabels: {}
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              role: management-ui
  • UI上で全てのポッドに対してアクセスができるようになったことを確認する
  • Frontend/Backend用のポリシーを落としてくる(一部書き換える必要があるので書き換える)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: stars
  name: backend-policy
spec:
  podSelector:
    matchLabels:
      role: backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: stars
  name: frontend-policy
spec:
  podSelector:
    matchLabels:
      role: frontend
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              role: client
      ports:
        - protocol: TCP
          port: 80
  • client -> frontend -> backendの通信ができることを確認する
  • デプロイしたリソースを削除する

Step23.5

ネットワークポリシーをVPCセキュリティグループとCloudWatchと統合する

  • TIGERAの無料トライアルに登録する
  • tsctlを落としてくる
  • CLUSTER_NAME/TS_TOKEN/VPC_ID/K8S_NODE_SGS/CONTROL_PLANE_SGを設定する
  • TSCEをインストールする
workshop:~/environment/calico_resources $ tsctl install --token $TS_TOKEN             --kubeconfig ~/.kube/config             --cluster-name $CLUSTER_NAME             --vpc-id $VPC_ID             --control-plane-sg $CONTROL_PLANE_SG             --node-sgs $K8S_NODE_SGS
[create] per-account AWS CloudFormationStack
[create] per-vpc AWS CloudFormationStack
[create] per-cluster AWS CloudFormationStack
[create] controller IAM User
[create] node IAM User
[create] controller Kubernetes ConfigMap
[create] ipsec Kubernetes Secret
[create] felix Kubernetes TLS Secret
[create] typha Kubernetes TLS Secret
[create] cni Kubernetes Manifest

Do you wish to proceed? (yes/no): [yes]: yes
[create] per-account AWS CloudFormationStack
AWS CloudFormationStack "tigera-cloudtrail" created
[create] per-vpc AWS CloudFormationStack
AWS CloudFormationStack "tigera-vpc-vpc-xxxxxxxxxxxxxxx" created
[create] per-cluster AWS CloudFormationStack
AWS CloudFormationStack "tigera-vpc-vpc-xxxxxxxxxxxxxxxxxx-cluster-eksworkshop-eksctl" created
[create] controller IAM User
AWS IAM User "tigera-vpc-vpc-xxxxxxxxxxxxxxx-TigeraControllerUser-1MIHF9C74402J" created
Kubernetes Secret "tigera-cloud-controllers-credentials" created
[create] node IAM User
AWS IAM User "tigera-vpc-vpc-xxxxxxxxxxxxxxx-cl-TigeraNodeUser-6OZEZOV317G3" created
Kubernetes Secret "calico-node-credentials" created
[create] controller Kubernetes ConfigMap
Kubernetes ConfigMap "tigera-aws-config" created
[create] ipsec Kubernetes Secret
Kubernetes Secret "ipsec-psk" created
[create] felix Kubernetes TLS Secret
Kubernetes CertificateSigningRequest "felix-tls-secret.kube-system" created
Kubernetes Secret "felix-tls-secret" created
[create] typha Kubernetes TLS Secret
Kubernetes CertificateSigningRequest "typha-tls-secret.kube-system" created
Kubernetes Secret "typha-tls-secret" created
[create] cni Kubernetes Manifest
INFO[2019-10-02T06:16:17Z] Installation complete. Waiting for Tigera Secure CE to become ready... 
INFO[2019-10-02T06:16:30Z] Cluster GUID: xxxxxxxxxxxxxxx 

step 23に戻ります

  • EC2インスタンスを構築する(webserverをなんでもいいからいれる 今回はnginxを使用)
  • kubectlでbusybox(name: test1)を立ち上げて立ち上げたEC2の80に対してwgetする
/ # wget -q -O - 192.168.105.198 | grep Welcome
        <h1><strong>Welcome to Setec Astronomy</strong> on the Amazon Linux AMI!</h1>
/ # Session ended, resume using 'kubectl attach test1-694d85bf95-sft4c -c test1 -i -t' command when the pod is running
  • 同様にkubectlでbusybox(name: test2)を立ち上げて立ち上げたEC2の80に対してwgetする
/ # wget -q -O - 192.168.105.198 | grep Welcome
        <h1><strong>Welcome to Setec Astronomy</strong> on the Amazon Linux AMI!</h1>
/ # Session ended, resume using 'kubectl attach test2-577f8bf79c-44mqd -c test2 -i -t' command when the pod is running
  • EKSのVPCに対してセキュリティグループを作成する
  • EC2を立ち上げるときに設定したprotect-sa-sgのinboundのHTTP通信をallow-sa-sgからのみに変更する
  • test1のpodに対してセキュリティグループ(allow-sa-sg)のannotationを付与する
kubectl annotate pod test1-694d85bf95-sft4c aws.tigera.io/security-groups='["sg-0cb8a3d4bb6245e29"]'
  • 再度それぞれのpodからwgetを実行し、test1からは許可され、test2は拒否されることを確認する
workshop:~/environment/calico_resources $ kubectl attach test1-694d85bf95-sft4c -c test1 -i -t
If you don't see a command prompt, try pressing enter.
/ # wget -q -O - 192.168.105.198 | grep Welcome
        <h1><strong>Welcome to Setec Astronomy</strong> on the Amazon Linux AMI!</h1>

workshop:~/environment/calico_resources $ kubectl attach test2-577f8bf79c-44mqd -c test2 -i -t
If you don't see a command prompt, try pressing enter.
/ # wget -q -O - 192.168.105.198 | grep Welcome
^C
/ # wget -q -O - 192.168.105.198 --timeout=10
wget: download timed out
  • CloudWatch Metricsで収集したデータを確認する
  • CloudWatch Logsで通信に失敗したログを確認する
  • default namespace内の通信を全て拒否するネットワークポリシーをデプロイする
  • 過去にデプロイしたマイクロサービスを再度デプロイする
  • frontendに対してブラウザからCLBを通してリクエストを送れるようにする(自作ステップ)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: ecsdemo-frontend
spec:
  podSelector:
    matchLabels:
      app: ecsdemo-frontend
  ingress:
    - from: []
      ports:
        - port: 3000
  • nodejs/crystalに対してリクエストが失敗したことをflowlogで確認する

  • nodejs/crystalに対してリクエストが成功するようにnetwork policyを適用する
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: ecsdemo-nodejs
spec:
  podSelector:
    matchLabels:
      app: ecsdemo-nodejs
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: ecsdemo-frontend
      ports:
        - port: 3000

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: ecsdemo-crystal
spec:
  podSelector:
    matchLabels:
      app: ecsdemo-crystal
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: ecsdemo-frontend
      ports:
        - port: 3000
  • frontendに対してリクエストが成功することを確認する