Kubeviousでkubernetesの状態を確認する

Kubevious is 何?

kubeviousとはkubernetestの設定をビジュアルに確認できるオープンソースソフトウェアです。これだけだと他にも似たようなツールはあるのですが、いくつか面白い機能があったので触ってみました。

実際に動作するデモが用意されていますのでインストールする必要もありません。なにわともあれ触ってみましょう。
基本的には状態を参照するだけのツールとなっており、今のところ設定の変更はできないようです。
demo.kubevious.io

Namespaceごとに構成しているリソースががまとめられて表示されています。見たいNamespaceを選択するとDeployment、Service、ServiceAccount、Config等々の各リソースの詳細を確認することが可能です。
例えばDeploymentを選択するとManifestの内容が確認できます。
f:id:cloudfish:20200427172400p:plain
f:id:cloudfish:20200427172549p:plain

主な機能

Detects Configuration Errors

設定エラーや使われていないリソースがあったりするとAler欄にその内容を表示してくれます。
f:id:cloudfish:20200427175424p:plain
f:id:cloudfish:20200427175500p:plain

Enables Full Text Search

設定内容から全文検索が可能です。例えば8080で検索すると以下のようにポート8080を利用している箇所がヒットします。Grepよりインタラクティブに結果が確認できるのでサクッと設定内容を検索したい場合は便利だと思います。
f:id:cloudfish:20200428081234p:plain

Radioactive & Overprivileged Workloads

特権コンテナや、ホストのネットワークを利用しているリソースなどを放射能マークで知らせてくれます。
f:id:cloudfish:20200428081906p:plain
f:id:cloudfish:20200428091949p:plain

Time Machine

Kubeviousで一番面白そうな機能がこのTIme Machineです。
過去の設定内容を時間を遡って確認することが可能です。例えばreplica数の変更タイミングと以前の設定値をTimelineを遡ることで確認が可能です。githubマニフェストを管理してGitOpsを実践していれば差分や変更タイミングは把握できると思いますが、こういった形でビジュアルに確認できるのは面白いですね。
f:id:cloudfish:20200428091823p:plain
f:id:cloudfish:20200428091421p:plain

Kubeviousのデプロイ

インストールは特にハマることはなく以下のコマンドデプロイできました。

kubectl create namespace kubevious
helm repo add kubevious https://helm.kubevious.io
helm upgrade --atomic -i kubevious kubevious/kubevious --version 0.5.9 -n kubevious

ポートフォワードでアクセスします。

kubectl port-forward $(kubectl get pod -l k8s-app=kubevious-ui -n kubevious -o jsonpath="{.items[0].metadata.name}") 3000:3000 -n kubevious

以下のURLにアクセスするとKubeviousが表示されます。
http://localhost:3000
f:id:cloudfish:20200428092103p:plain

まとめ

Production環境で使うほどのツールではないかもしれませんが、Staging環境などで設定漏れや使ってないリソースの確認など俯瞰的に状態を確認したりするのにはすごく便利なツールではないでしょうか。できればクラスタを一括管理できればもっと便利に使えるかもしれませんね。みなさん興味があれば是非使ってみてください。

参考

github.com

Building Apache Guacamole with AWS Fargate and Aurora Serverless


f:id:cloudfish:20200417102427p:plain:w200
Gucamole is very useful tool as Windows Bastion host.I'd like to introduce to build Apache Guacamole with AWS Fargate.
I can build Gucamole with docker-compose, but I considered scale out If there are more increase RDP connections.So, I have choosen building with AWS Fargate because it's easy to scale out.
In the first place ,Can the Guacamole scale out ?I didn't find it at the official documentation.I found that somebody ask it in mailing list, the answer was yes because of using proper transactions. I believe this answer, I decided to build with AWS Fargate for scaling.
AWS Fargate is a serverless compute engine for containers without need to manage Fargate Hosts.
Unlike EKS, we don't need to pay for control plane. you only pay amount of using fargate container.We can focus building application.
And the reason of choosing Aurora Serverless is cheap of the cost, because it will stop if you don't access by constantly. Also it's scaled out if neccesarry. Currently, the number of users is low, don't need high performance. threfore, the first access is acceptable even if it is late.
So let's get started!

Prerequisite

Overview

The point of this configuration.

  • Host guacd and gucamole on Fargate
  • Host mysql on Aurora Serverless
  • Manage user info on SimpleAD

Note that the recording function is not used this time.

Diagram

f:id:cloudfish:20200425085325p:plain

1. SImpleAD

Create SimpleAD as follows

DirectoryType small
Domain any name

You can add users from the Workspaces service without launching Workspaces.

2.Aurora Serverless

2.1 Create Database instance

Create it with the following settings. Here are the main settings

Engine options Amazon Aurora
Edition Amazon Aurora with MySQL compatibility
Version latest
Database Location Regional
Database features Serverless
DB cluster identifie any name
Minimum Aurora capacity unitInfo 1
Maximum Aurora capacity unitInfo 1
Additional scaling configuration check 'Pause compute capacity after consecutive minutes of inactivity'
Web Service Data API check 'Data API'

When you're done creating,you memo RDS Endpoint.

2.2 Save the mysql password to Parameter Store

Setting parameter store for mysql password.
This is referenced from fargate container.

Name /guacamole/mysql_password
Tier Standard
Type SecureString
Value {YOUE_MYSQL_PASSWORD}
2.3 Initialize DB

Executing the following command for creating initialize SQL.

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

Open the Query Editor in AWS Console.
Paste and execute the contents of initdb.sql.
f:id:cloudfish:20200425113621p:plain

3. Application Load Balancer

3.1 Create Target Group

Create target group as follows

Target Type IP
Protocol HTTP
Port 8080

HealthCheck

Protocol HTTP
Path /guacamole
Stickiness Enable
Stickiness duration 3600
3.2 Create Application Load Balancer
Load Balancer Type Application Load Balancer
Scheme internet-facing

Listener

HTTPS 443 Created TG by 1.1
HTTP 8080 Created TG by 1.1

4. Create Fargate Cluster

4.1 Create Security Group

Create new SecurityGroup as follows for fargate task.

Protocol Port Source
TCP 8080 SecurityGroup of ALB

When it complete, you modify SecurityGroup of RDS.
Add the following setting.

Protocol Port Source
TCP 3306 SecurityGroup of Fargate task
4.2 Create Fargate Cluster.

Execute the following command for creating cluster.

ecs-cli configure \
--region ${YOUR_REGION_CODE} \
--cluster ${CLUSTER_NAME} \
--default-launch-type FARGATE \

ecs-cli up \
--cluster-config $CLUSTER_NAME \
--vpc ${VPI_ID} \
--subnets ${SUBNET_ID_1},${SUBNET_ID_2}
4.3 Run the Guacamole Service

ecs-params.yml
create ecs-params.yml file as follows.
Set the variables according to your environment.

version: 1
task_definition:
  task_role_arn: ${TASK_ROLE_ARN}
  task_execution_role: ${TASK_EXECUTION_ROLE}
  ecs_network_mode: awsvpc
  task_size:
    mem_limit: 0.5GB
    cpu_limit: 256
  services:
    guacamole:
      secrets:
        - value_from: /guacamole/mysql_password
          name: MYSQL_PASSWORD

run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - ${SUBNET_ID_1}
        - ${SUBNET_ID_2}
      security_groups:
        - ${SECURITY_GROUP_ID_FOR_TASK}

docker-compose.yml
create docker-compose.yml file as follows.
Also set the variables according to your environment.

version: "3"

services:
  guacd:
    image: guacamole/guacd:latest
    expose:
    - "4822"
    ports:
    - "4822:4822"
    logging:
      driver: awslogs
      options:
        awslogs-group: guacamole
        awslogs-region: ap-northeast-1
        awslogs-stream-prefix: guacd
    environment:
    - GUACD_LOG_LEVEL=debug
  guacamole:
    image: cloudfish/guacamole:latest
    ports:
    - "8080:8080"
    logging:
      driver: awslogs
      options:
        awslogs-group: guacamole
        awslogs-region: ap-northeast-1
        awslogs-stream-prefix: guacamole
    environment:
    - GUACD_HOSTNAME=localhost
    - LDAP_HOSTNAME=${SIMPLE_AD_IP}
    - LDAP_PORT=389
    - LDAP_ENCRYPTION_METHOD=none
    - LDAP_USER_BASE_DN=CN=Users,DC=guacamoleDC=local
    - LDAP_USERNAME_ATTRIBUTE=CN
    - LDAP_CONFIG_BASE_DN=CN=Users,DC=guacamole,DC=local
    - TOTP_ENABLED=false  # If you want to use MFA, set true
    - MYSQL_HOSTNAME=${RDS_ENDPOINT}
    - MYSQL_DATABASE=guacamole
    - MYSQL_USER=guacamole

Launching the Service
Execute the following command and start Gucamole service.

ecs-cli compose \
--file docker-compose.yml \
--ecs-params ecs-params.yml \
--project-name  guacamole-service \
service up \
--force-deployment \
--target-group-arn ${TARGET_GROUP_ARN} \
--container-name guacamole \
--container-port 8080

When If it's running properly, you can see the screen as follows on ECS Task screen. If it's not running, you check cloudwatch logs.
f:id:cloudfish:20200425143921p:plain

Login
Now, Let's get access to login screen.Access the following URL.If Aurora Serverless is stopped,It's going to take some time.
https://YOUR_DOMAIN/guacamole
You can see the this screen.
f:id:cloudfish:20200425213044p:plain:w300

You can logged in by the following ID/PASS.
USER:guacadmin
PASSWORD:guacadmin

f:id:cloudfish:20200425214230p:plain

Register target device you want to connect, you try to connect with RDP. But I won't go into how to connect it in detail.

In this configuration, the recording function is not available, because this architecture don't have storage.But Fargate can be available EFS in platform 1.4. therefore, I'm sure you can use the EFS to record.

Apache Guacamoleを使ってWindowsServerにセキュアにログイン


f:id:cloudfish:20200417102427p:plain:w200
 諸事情により社内で複数担当者が共通ユーザーでWindowsServerにアクセスして実施している業務がありました。こうした運用はよくあるのではないでしょうか。当然ながら共通ユーザーでアクセスすることに問題があることは認識していますが、アクセスについては社内からのみとアクセス制限を行っていたため現状では特に対応を行っていませんでした。
 しかしながら、昨今の急激なリモートワークへの移行に伴って、自宅からの接続も許可する必要が出てきましたが、現状オフィスへのVPN接続環境はないため、このままだと対象のWindowsマシンのセキュリティグループ設定でRDP接続の接続元をフル解放するか都度作業者のIPを許可する必要に迫られました。とはいえどちらの方法もあまり現実的ではないので、別な手段を探していたところ、GuacamoleというブラウザからRDP接続ができるツールを見つけたので、これをRDP接続するための踏み台サーバとして利用することで共通ユーザー問題を解決できると考え導入を進めています。今回はこれについて紹介したいと思います。

Apache Guacamoleとは

Guacamole(ワカモレもしくはガカモレと読むそうです)とはクライアントレスなリモートデスクトップゲートウェイです。また、接続クライアントに特別なプラグインやソフトウェアなどをインストールせずに、ブラウザからVNC、RDP、SSH接続などが可能となっています。

Guacamoleの主な機能

主に以下のような機能が提供されており、作業端末やサーバーへのアクセスにおいて、セキュリティの強化や問題が発生した際のトレースが行いやすくなっています。また、今回Guacamoleを使う大きな理由の一つとして、管理者側で接続可能な端末を登録して誰に接続させるかをコントロールできる機能があります。そのため利用者側は接続情報(ユーザー、パスワード)を意識する必要がありません。言い換えると利用者側はユーザー、パスワードを知ることができないことになります。

  • ブラウザからVNC、RDP、SSH、SFTP、TELNET接続が可能
  • DBでの認証、LDAPOpenIDなどで認証やMFA(多要素認証)が利用可能
  • 端末へのアクセスログが保存されているため、いつ誰がどの端末へアクセスしたのかトレースが可能
  • 管理者と一般ユーザーの権限分離が可能
  • 画面操作内容の録画

Gucamoleの構成

詳細は公式ドキュメントを確認してもらうとして、主に二つのコンポーネントで構成されています。

guacamole

ユーザーからのアクセスを受け付けるWebアプリケーション

guacd

RDP、VNCSSH接続などを行うコンポーネント
guacamole.apache.org

現状の課題と解決策

本来であればWindowsをAD運用することが一番いいのですが、現状すぐにはその対応はできないというのが前提にあります。

1.ユーザー管理

現状では、ユーザー管理ができていないため、SimpleADを使ってGucamoleのユーザー管理を行います。もい担当者が異動や退職となって業務を外れた場合は、対象ユーザーを削除します。削除されたユーザーはGucamoleにログインできないため、業務用のWindowsServerへもログインでき無くなります。

2.WindowsServerへ共通ユーザーでログイン

WindowsServerへの接続情報はGucamoleだけが保持する事になるので、利用者が知ることはできません。そのため、担当者の退職などによりパスワードの再設定、再配布などの対応が不要になります。

3.いつ誰がアクセスしたか分からない

Gucamole側でいつ誰がどの端末にアクセスしたかログを保持しているため、Windows側は共通ユーザーでログインされていたとしてもGucamole側のログを確認することでトレースが可能となります。

4.社外からもアクセスする必要がある(オフィスにVPN環境がないためIP制限できない)

WindowsへのアクセスはGucamoleサーバからのみアクセス可能として、Gucamoleサーバーに対してはどこからでもログイン可能とする。認証方法をSImpleAD+MFAとすることでログイン時のセキュリティ向上を行います。

構成

実際の構成はVPCが別れていたりするのでもう少し複雑にはなるのですが、ここではシンプルな構成とします。以下のようにGucamoleサーバーを踏み台として配置することでWindowsServerをPrivateSubnetに配置することが可能になります。
f:id:cloudfish:20200420152133p:plain:w300

構築手順

Gucamoleのインストール方法については、サーバーにwarファイルを展開して直接インストールする方法もありますが、Dockerでインストールする方が簡単なので今回はこちらの方法で構築を行います。また、有償にはなりますがMarketPlaceでイメージ(Guacamole Bastion Host)が公開されているものもありますので興味のある方はそちらもご覧ください。

SimpleADの構築

ユーザー管理用のSimpleADを構築します。SimpleADの構築方法については以下のブログを参照してください。
以下の設定で構築してください。ドメイン名は適当な名称を設定してください。

DirectoryType small
ドメイン guacamole.local
VPC Gucamoleを構築するVPC
Subnet 上記のVPCのPrivateSubnet

ユーザーの作成については、WorkSpacesの設定から追加が可能なのでGucamoleのログイン用ユーザーを作成しておいてください。こちらも以下のブログに追加方法がありますので参照してください。間違ってWorkspacesの立ち上げまではしないようにしてください。
Simple ADを利用したWorkSpaces構築手順 – サーバーワークスエンジニアブログ

ELBの準備

ELBはApplicationLoadBalancerを利用します。こちらも詳細は他のブログを参照してください。また、カスタムドメインを使用する場合は、必要に応じてACMなり自己証明書なりを準備しておいてください。

TargeteGroupの設定
ターゲットグループ名 任意
ターゲットの種類 インスタンス
プロトコル HTTP
ポート 8080
VPC Gucamoleを構築するVPC

■ヘルスチェック

プロトコル HTTP
パス /gucamole
ALBの設定
ELBのタイプ Application Load Balancer
VPC Gucamoleを構築するVPCを設定
Subnet 上記のVPCのPublicSubnet

■リスナー設定

Protocol Port 転送先TG
HTTPS 443 上記ターゲーットグループ
HTTP 8080 上記ターゲーットグループ

※証明書を準備していない場合はHTTPのみ設定してください。

Amazon Linuxの準備

起動

Gucamole用のEC2を作成します。Amazon Linuxで構築します。

AMI: 最新のAmazonLinux2
インスタンスタイプ: t3.micro
VPC: Gucamoleを構築するVPCを設定
Subnet: 上記のVPCのPublicSubnet
SecurityGroup: 8080がALBから疎通可能となるよう設定

起動が完了したら作成したターゲットグループにアタッチしてください。なお、この時点ではhealthyになりません。

Dockerインストール

次にDockerをインストールします。
以下のコマンドを実行してdockerとdocker-composeをインストールします。

dockerのインストール

sudo yum install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker

docker-composeのインストール

sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

gucamoleのイメージ構築

guacamole(gucamole-client)のイメージは公式からDocker Hubでバージョン1.1.0提供されていますが、1.1.0にはMFAの設定が組み込まれていません。そのため、githubから最新のコードをチェックアウトして自分でイメージのビルドを行います。

以下のコマンドを実行してイメージを作成します。
ビルドにはかなりの時間がかかりました。

git clone https://github.com/apache/guacamole-client.git
cd guacamole-client
docker build -t guacamole_120 .

docker-composeの作成

Dockerで構築する場合、以下の3つのコンテナが必要となります。

  • guacamole
  • guacd
  • mysql(or postresql)

以下の内容でdocker-compos.yamlを作成します。
$SIMPLE_AD_IPには作成したSimpleADのIPを設定します。
LDAP_USER_BASE_DN、LDAP_CONFIG_BASE_DNのDCにはSimpleAD作成時に設定したドメインを設定してください。

version: "3"

services:
  guacd:
    image: guacamole/guacd:latest
    expose:
    - "4822"
    environment:
    - GUACD_LOG_LEVEL=debug
  guacamole:
    image: guacamole_120
    links:
      - guacd:guacd
    ports:
    - "8080:8080"
    environment:
    - GUACD_HOSTNAME=guacd
    - LDAP_HOSTNAME=$SIMPLE_AD_IP
    - LDAP_PORT=389
    - LDAP_ENCRYPTION_METHOD=none
    - LDAP_USER_BASE_DN=CN=Users,DC=guacamole,DC=local
    - LDAP_USERNAME_ATTRIBUTE=CN
    - LDAP_CONFIG_BASE_DN=CN=Users,DC=guacamole,DC=local
    - TOTP_ENABLED=true
    - MYSQL_HOSTNAME=mysql
    - MYSQL_DATABASE=guacamole
    - MYSQL_USER=guacamole
    - MYSQL_PASSWORD=guacamole

  mysql:
    image: mysql/mysql-server:5.7
    volumes:
    - "./mysql/data:/var/lib/mysql"
    - "./mysql/init:/docker-entrypoint-initdb.d"
    environment:
    - MYSQL_DATABASE=guacamole
    - MYSQL_USER=guacamole
    - MYSQL_PASSWORD=guacamole

ディレクトリの作成

docker-compose.yamlファイルと同じ階層に以下のディレクトリを作成します。

mkdir -p mysql/data
mkdir -p mysql/init
tree -d mysql/
mysql/
├── data
└── init

初期データ作成

以下のコマンドで初期化用のスクリプトを作成します。

docker run --rm guacamole_120 /opt/guacamole/bin/initdb.sh --mysql > mysql/init/initdb.sql

起動

docker-compose up -d

Gucamoleの使い方

接続用のWindowsServerについては事前に用意し、Gucamoleサーバーからポート3389で疎通できるようにしておいてください。

ログイン画面にアクセス

カスタムドメインを設定していなければ、以下のいずれかのURLでアクセスしてください。
https://ELB_DNS/guacamole/
http://ELB_DNS:8080/guacamole/
正常に起動されていれば以下のようなログイン画面が表示されます。もし表示されていなければ、ログを確認してみてください。

以下のユーザー、パスワードでログインできます。
ログインユーザー: guacadmin
パスワード: guacadmin
f:id:cloudfish:20200420190016p:plain:w200

MFA設定

MFAが有効になっていますのでGoogle Authenticatorなどで設定してください。
f:id:cloudfish:20200420194326p:plain:w200

初期画面

以下のような初期画面が表示されます。
f:id:cloudfish:20200420200648p:plain

接続設定の追加

右上のユーザー名から「設定」を選択し、「接続」タブを開いて「接続の追加」をクリックします。
以下の通り入力を行い保存します。
f:id:cloudfish:20200421090135p:plain

接続情報の選択

右上のユーザー名からホーム画面に戻ると、先ほど登録した接続設定が表示されていますので、登録した接続情報を選択します。
f:id:cloudfish:20200421091255p:plain

RDP接続

以下のようにリモートデスクトップが開きます。
f:id:cloudfish:20200421092011p:plain

RDPの切断

切断するにはMacの場合は、「Ctrl + Shift + Option」でサイドバーが表示されますので「切断」を選択してください。
f:id:cloudfish:20200421092248p:plain:w300

他のユーザーが利用中の場合

また、別ユーザーが接続中の場合、以下のように利用中であることが分かります。ただし、日本語表記はバグのためが表示されないため、英語表記とする必要があります。日本語だと他にも微妙な動作があったりもしたので基本は英語表記の方がいいかもしれません。
なお、接続設定において最大接続数を1とすると他のユーザーが利用中の場合は接続できないような制限をかけることが可能です。
f:id:cloudfish:20200421094831p:plain

MFAの再設定

多要素認証の機能を利用するので、スマホの故障や紛失による再設定をどのように対応するのか調べてみました。現状では管理者がUIから設定する方法はなさそうです。
そのため、DBを直接いじる必要があるようです。

以下のSQLで対象のユーザーIDを特定し

select 
    gu.user_id 
from 
    guacamole_entity ge inner join guacamole_user gu 
on ge.entity_id = gu.entity_id 
where ge.name='guacadmin'

対象ユーザーの「guac-totp-key-confirmed」属性をfalseに戻すことで、MFAの再設定が可能となります。

update 
    guacamole_user_attribute 
set attribute_value='false' 
where 
    attribute_name='guac-totp-key-confirmed' 
and user_id=${USER_ID}

Workspacesについて

検証しながら気が付いたのですが、この接続の仕組みをWorkSpacesでも利用できることに思い至りました。
WorkSpacesについては、そもそも業務都合上、利用者が自宅でも接続できる必要があるため、IP制限ができず専用のクライアントツールがあればどこからでもユーザー、パスワードでログイン可能となることが悩みとしてありました。
そのため、WorkSpacesについてもGucamole経由でアクセスすることで認証をMFAを使ってセキュアにすることができかつアクセス状況もトレースが可能となります。
設定方法の詳細は割愛させていただきますが、WorkSpacesに割り当てられているENIにアタッチされたセキュリティグループにGucamoleサーバーから3389で疎通可能となるルールを設定することで、RDPで接続が可能となります。さらにIPアクセスコントールでルールなしの状態で設定すると、クライアントツールからは接続ができません。ただし、この方法は実行モードが「AutoStop」モードでは利用できないので注意してください。

まとめ

Apache Gucamoleについては、Windowsマシンへアクセスするための踏み台としてすごく便利だと思いました。特に管理側としてアクセス状況のトレースがしやすいというのは非常にありがたい機能だと思います。今回は、共通ユーザーの問題があったので、Gucamoleにたどり着きましたが、全てのAWS上へのWindowsマシンへのアクセスは基本的にこれを利用する方式にしようかと考えています。もし同じような悩みを抱えている場合は、利用を検討してみてください。

EKSクラスタのバージョンアップ手順

f:id:cloudfish:20200116173700p:plain
3/10にEKSでKubernetesのバージョン1.15のサポートが開始されたことに伴いバージョン1.12が5/11でサポート対象外となります。そのため、現在のバージョンが1.12の場合は速やかなアップデートが必要になります。Kubernetesについてはリリースサイクルが早く、最新の3つまでしかサポートされないため可能な限り追従していく必要があります。今回はバージョン1.12のクラスタをアップデートしましたのでその手順について紹介したいと思います。

バージョンアップに関しての考慮ポイント

EKSのリリースサイクル

Kubernetesのリリースサイクルは年4回となっておりおよそ3ヶ月に1回新しいバージョンがリリースされます。EKSもこれに追従しているため、ほぼ同じようなサイクルとなっています。

サポートバージョン

サポートについては最新の3つのバージョンをサポートします。今回であれば、1.15、1.14、1.13がサポートされ、1.12については2020/05/11でサポート廃止となります。そのため、最低、年に1回はバージョンアップが必要となります。

サポート停止日以降に古いバージョンで実行している場合は自動更新

今回のケースでは2020/05/12以降にバージョン1.12のままであれば自動的に1.13に更新されます。
ただし、自動で更新されるのはコントロールプレーンのみとなるためワーカーノードについては自分で更新する必要があります。

クラスタの更新中のアプリケーションへの影響

実行中のアプリケーションは影響を受けないとありますが、注意書きにもあるとおりAPIサービスが短時間中断する場合があるとのことなので、軽微かもしれませんが全く影響を受けないわけではないと思います。実際のアップデート作業ではメンテナンス時間帯を設定しておいた方が安全かと思います。

クラスタの更新に失敗するケース

クラスタの更新については自動で更新されるとはいえ必ず成功するわけではなく失敗する場合もあります。更新に失敗した場合は、そのままの状態で放置されることはなく必ずロールバックされます。以下の条件が満たされない場合は更新に失敗する場合があるようです。

  • クラスターの作成時に指定したサブネットから、2~3の空きIP アドレスがない場合。
  • クラスターの作成時に指定されたいずれかのサブネットやセキュリティグループが削除された場合

マスターとワーカーノードの互換性

Kubernetes では、少なくとも 2 つのマイナーバージョンにおいて、マスターとワーカーノード間の互換性をサポートしています。
例として
マスター(kube-apiserver)が1.15の場合
ワーカーノード(kubelet)は1.15、1.14および1.13がサポートされます。

バージョンアップ手順

今回はバージョン1.12から1.14へ以下の手順でアップデートを行いました。1.15はリリースされたばかりということもあり、1.14へアップデートを行いました。

手順概略

アップデート手順の概略については以下のような流れになります。
1.クラスタアップデート
2.kube-proxyアップデート
3.corednsアップデート
4.cniアップデート
5.(新バージョン)ノードグループ追加
6.(旧バージョン)ノードグループ削除

事前準備

バージョン確認

まずは現行のバージョンを確認しましょう。以下のコマンドを実行してバージョンを確認してください。

#クラスタバージョン
kubectl version --short
#ワーカーノードバージョン
kubectl get nodes
#kube-proxyバージョン
kubectl describe daemonset kube-proxy --namespace kube-system | grep Image | cut -d "/" -f 3
#corednsバージョン
kubectl describe deployment coredns --namespace kube-system | grep Image | cut -d "/" -f 3
#CNIバージョン
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

確認結果

マスター ワーカーノード cni kube-proxy coredns
現行バージョン Server Version: v1.12.10-eks-aae39f v1.5.0 v1.12.7 v1.12.6 v1.2.2

クラスタのバージョンアップ後にアドオンについてもバージョンアップを行う必要があります。各種アドオンのバージョンアップが必要かどうかは以下の表を確認してください。上記のケースの場合全てのアドオンのバージョンアップが必要となります。

Kubernetes Version 1.15 1.14 1.13 1.12
Amazon VPC CNI plug-in 1.5.5 1.5.5 1.5.5 1.5.5
DNS (CoreDNS) 1.6.6 1.6.6 1.6.6 1.6.6
KubeProxy 1.15.10 1.14.9 1.13.12 1.12.10

上記の表からアップデート後の想定バージョンは以下となります。

マスター ワーカーノード cni kube-proxy coredns
更新後バージョン Server Version 1.14.9 v1.4.9 v1.5.5 v1.4.9 v1.6.6
ポッドセキュリティポリシーの設定確認
kubectl get psp eks.privileged

以下のようなエラーが出た場合は、ポッドセキュリティポリシーをインストールする必要があります。

Error from server (NotFound): podsecuritypolicies.extensions "eks.privileged" not found

ポッドセキュリティポリシーのインストールは以下を参照してインストールしてください。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/pod-security-policy.html#install-default-psp

バージョンアップ

バージョンアップ作業については、マネジメントコンソール、eksctl、aws-cliの3つで作業が可能ですが、今回はeksctlコマンドでの手順を紹介します。なお、eksctlコマンドのバージョンは0.14以降となります。また、可能ならサービスは止める調整をしておいたほうがいいと思います。

クラスタのバージョンアップ(1.12→1.13)

まずはクラスタを1.12から1.13へバージョンアップを行いますので、以下のコマンドを実行してください。時間は10~15分程度かかりました。

eksctl update cluster --name ${eks-cluster-name} --approve

完了後に以下のコマンドでバージョンを確認してください。

kubectl version --short
クラスタのバージョンアップ(1.13→1.14)

1.13へのバージョンアップが完了したら、次は1.14へバージョンアップを行います。先ほどと同様に以下のコマンドを実行してください。時間は20-25分程度かかりました。

eksctl update cluster --name ${eks-cluster-name} --approve

完了後に以下のコマンドでバージョンを確認してください。

kubectl version --short
kube-proxyバージョンアップ(→1.14.9)

クラスタのバージョンが1.14なのでそれに対応するkube-proxyのバージョンは1.14.9となります。以下のコマンドでバージョンアップを実行します。

kubectl set image daemonset.apps/kube-proxy \
    -n kube-system \
    kube-proxy=602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/kube-proxy:v1.14.9

以下のコマンドでバージョンアップされているか確認します。

kubectl describe daemonset kube-proxy --namespace kube-system | grep Image | cut -d "/" -f 3
corednsバージョンアップ(→1.6.6)

corednsの現行バージョンが1.2.2のため、1.6.6へバージョンアップを行います。以下のコマンドを実行します。

kubectl set image --namespace kube-system deployment.apps/coredns \
coredns=602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/eks/coredns:v1.6.6

以下のコマンドでバージョンアップされているか確認します。

kubectl describe deployment coredns --namespace kube-system | grep Image | cut -d "/" -f 3
cniバージョンアップ(1.5.5)

cniの現行バージョンが1.12.7のため、1.5.5へバージョンアップを行います。以下のコマンドを実行します。

kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.5/config/v1.5/aws-k8s-cni.yaml

以下のコマンドでバージョンアップされているか確認します。

kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
新バージョンでノードグループ作成

以下のコマンドで新しくノードグループを作成します。
パラメータは必要に応じて変更してください。cluster.yamlファイルを作成している場合は、バージョンを変更して実行してください。

eksctl create nodegroup \
--cluster default \
--version 1.14 \
--name ${eks-cluster-name} \
--node-type m5.large \
--nodes 2 \
--nodes-min 1 \
--nodes-max 4 \
--node-ami auto

ワーカーノードのバージョン確認

kubectl get nodes
旧バージョンのノードグループ削除
eksctl delete nodegroup --cluster= ${eks-cluster-name} --name= ${eks-workernode-name}

バージョン1.12から1.15へバージョンアップ

もし1.12から1.15へバージョンアップを行う場合は、マスターとワーカーノードの互換性を考慮して作業手順を考える必要があります。クラスタのバージョンを一気に1.15に上げると、ワーカーノードのバージョンが1.12なので互換性が保証されていない状態となります。そのため、以下のように1.15にアップする前に一度ワーカーノードのバージョンをアップしておくほうが安全かと思います。

  • クラスタのバージョンアップ(1.12→1.13)
  • クラスタのバージョンアップ(1.13→1.14)
  • ワーカーノードのバージョンアップ(1.12→1.14)
  • クラスタのバージョンアップ(1.14→1.15)
  • ワーカーノードのバージョンアップ(1.14→1.15)

まとめ

バージョンアップについては、可能であればブルー・グリーンデプロイで切り替える方が安全にバージョンアップが可能だと思います。今回は諸々の制約により現行のEKSクラスタをアップデートする手法を選択しました。
Kubernetesのリリースに追従していく必要があるとはいえ、バージョンアップ作業については、作業手順の確立や関係者の調整なども含めて対応に時間がかかるので先送りにしがちではないでしょうか。
しかしながら、Kubernetesを使うのであれば定期的なバージョンアップ作業も運用の一環として考えていく必要があると思いますので、ぜひ手順を確立するようにしてみてください。

sshuttleで簡易VPN的環境の構築

 昨今のテレワークブームはいかがお過ごしでしょうか?突然の世の中の働き方の転換を迎え、特に社内システム担当の方は非常に大変な状況に見舞われているのではないかと思います。
 ゼロトラストやBeyondCorpなど最先端の企業ではもはやVPNは使わないといったことが取りざたされていますが、実際のところ一足飛びにそういった環境が用意できる訳でもなく、普段からそういったセキュリティポリシーをしっかりと考え仕組みを構築している企業だからこそ可能な取り組みかと思います。
 そういう意味では、やはり昔ながらのVPNというのが簡単かつセキュアにリモートネットワークにアクセスする仕組みになるかと思いますが、そうした環境の構築も少なからず時間がかかるものになります。今回はそうした方々が簡単に導入可能なsshuttleという簡易なVPN環境が構築できるツールを紹介したいと思います。タイトルには簡易VPNと書きましたが、正確にはVPNではありませんのでご注意ください。
 これはSSHができる踏み台サーバーさえあれば、クライアント側でsshuttleをインストールするだけで利用可能になるため導入が非常に簡単なツールになります。

できること

  • ssh経由でリモートのネットワークにアクセスができる
  • リモートネットワークのWebサーバやファイルサーバにポートフォワードを設定しなくてもアクセスが可能

イメージ図

f:id:cloudfish:20200306171654p:plain

前提条件

SSH接続可能なサーバーが構築されていること

インストール方法

sshuttleはクライアント側にインストールするだけになります。
Macの場合のインストール方法は以下になります。

brew install sshuttle

Mac以外は以下を参照してください。残念ながらWindowsは対象外です。未検証ですがWSLから利用できるかもしれません。
github.com

接続方法

上記イメージ図の構成の場合、ターミナルから以下のようなコマンドを実行します
ssh configに以下を設定

Host bastion
  HostName xxx.xxx.xxx.xxx
  User ec2-user
  IdentityFile ~/.ssh/bastion.pem

以下の接続コマンドを実行する

sshuttle --dns -r bastion 10.10.0.0/16

「--dns」オプションを付与しておくと、接続中はリモートネットワークのDNSが参照可能になります。これは結構良いオプションだと思います。例えば、AWSの場合だとRoute53でプライベートゾーンが作成できますが、接続中はローカル端末からもそのゾーンの名前解決が可能になります。
最後のCIDRの「10.10.0.0/16」は、リモートネットワークのCIDRを指定します。複数ある場合はスペース区切りで設定してください。

上記で接続中にしたままにすることで、後はSSHなりDB接続なりファイルサーバへの接続が可能になります。

よりセキュアに接続するには?

sshで公開鍵認証とはいえ、SSHをフル解放するのはあまり精神的によくありませんよね。そこでよりセキュアにする方法としては以下の方法が考えられます。

  • MFAによる多要素認証を行う
  • Session Managerを利用してSSH接続を行う

MFAによる多要素認証

利用者が在宅で作業する場合にはIP制限が難しいと思いますので、鍵認証に加えてMFAによる認証を行うことで、よりセキュアな構成が可能になります。設定方法については以下を参照してください。
また、この方法であればリモートネットワークがAWS以外の場合でも対応が可能です。
dev.classmethod.jp

セッションマネージャを利用してSSH接続を行う

こちらはリモートネットワークがAWS環境前提の話となりますが、踏み台となるサーバをパブリックサブネットではなく、プライベートサブネットに配置してセッションマネージャを使ってアクセスすることできるのでよりセキュアにできます。セッションマネージャについてはSSHが利用できるようになりましたので、これを通じてsshuttleの利用も可能となります。

** 設定方法
SSMエージェントやSession Managerプラグインのアップデートが必要となりますので、以下のブログを参照してアップデートしてください。
dev.classmethod.jp

接続方法

ssh config

ssh configに以下の設定を行います。INSTANCE_IDとAWS_PROFILEについては接続先のEC2のインスタンスIDとAWSアカウントのプロファイルを指定してください。

Host bastion
  User ec2-user
  IdentityFile ~/.ssh/bastion.pem
  ProxyCommand sh -c "aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartSSHSession --parameters 'portNumber=%p' --region=ap-northeast-1 --profile $AWS_PROFILE"
接続

以下のコマンドで接続が可能です。

sshuttle --dns -r bastion 10.10.0.0/16

まとめ

いかがでしょうか?検証してみた印象としては結構簡単に使えるのではないかと思いました。ただし、SSH接続が必要になりますのでエンジニア以外が利用するには少しハードルが高いかもしれませんが、利用してみる価値はあるのではないでしょうか。

aws-google-authとdirenvを使ってEKSのクラスタ切り替えを安全に行う

f:id:cloudfish:20200116173700p:plain:w300

みなさんEKSクラスタの切り替えはどうしてますか?kubectxを利用されている方は多いのではないでしょうか?
kubectxは切り替えは非常に便利なのですが、逆に便利すぎてクラスタの選択を誤って冷や汗をかいたということはないでしょうか。
私自身は10程度のEKSクラスタを扱っていますが、あえて利便性を落として自分がミスしにくいと思う方法で切り替えを行っています。
今回はこのEKSクラスタを安全に切り替える方法について紹介したいと思います。

前提条件

aws.amazon.com

  • aws-google-authがインストールされていること

github.com

検証していませんが、saml2awsでも同じことができると思います。

設定方法

aws-google-authやdirenvの設定方法についてはここでは触れませんので別途調べてみてください。

プロジェクトごとにディレクトリを構成する

- clusterが複数ある場合はプロジェクトのディレクト配下に配置
- clusterのディレクトリにkubeconfigを配置

ProjectA
 ├── cluster_1
 |     ├── .envrc   #direnv用設定
 |     └── .kube    #kubeconfig
 └── cluster_2
 |     ├── .envrc
 |     └── .kube
ProjectB
 └── cluster_1
 |     ├── .envrc
 |     └── .kube
 :
  • kubeconfigの配置

以下のコマンドで直下にkubeconfigを配置できます

aws eks --region ap-northeast-1 update-kubeconfig --name cluster_1 --kubeconfig=.kube/config
  • direnvを設定

- clusterのディレクトリ直下に以下の内容で.envrcを作成する

export KUBECONFIG=$(pwd)/.kube/config
export AWS_PROFILE=test_admin
#zshの場合は以下の設定で右側にawsのprofile名とクラスタ名が表示されます
CLUSTER_NAME=$(grep "cluster: arn:aws:eks" .kube/config |awk -F"/" '{print $2}')
export RPROMPT="%F{154}$AWS_PROFILE:$CLUSTER_NAME%f" 

AWS_PROFILE名はaws-google-authのログイン時に設定しdirenvで設定した名称と同一にする。

aws-google-auth -u hoge@gmail.com -I GOOGLE_IDP_ID -S GOOGLE_SP_ID -D -d 3600 -r arn:aws:iam::123456789012:role/test_admin -p test_admin -R ap-northeast-1

動作確認

cluster_1のディレクトリにcdすると以下のようにAWS_PROFILEとKUBECONFIGが環境変数に設定されます。

$cd cluster_a
direnv: loading .envrc
direnv: export +AWS_PROFILE +KUBECONFIG +RPROMPT
$                                                     test_admin:cluster_1

この後、aws-google-authで該当のAWSアカウントにログインすると、kubectlコマンドが利用できるようになります。

$kubectl get node                               test_admin:cluster_1
NAME                                               STATUS   ROLES    AGE   VERSION
ip-10-10-137-223.ap-northeast-1.compute.internal   Ready    <none>   58d   v1.14.7-eks-1861c5
ip-10-10-148-4.ap-northeast-1.compute.internal     Ready    <none>   58d   v1.14.7-eks-1861c5

仕組み

クラスタ毎にディレクトリを作成してその直下にkubeconfigを配置し、direnvでkubeconfigの切り替えを行います。また、aws-google-authを使いログインするとクラスタにアクセスできるようになります。 
 こうすることで該当のクラスタディレクトリにcdすることでクラスタの切り替えを行いつつ、aws-google-authを利用して不用意にクラスタにアクセスできないようにしています。また、AWSのプロファイル名をdirenvの環境変数と同一にしておくことによって、セッションが残っていたとしてもディレクトリを抜けることによってプロファイルが参照されなくなるので思わぬミスが減らせます。

ディレクトリを抜けてkubectlコマンドを実行した場合、以下のようなエラーになります。

$kubectl get node
The connection to the server kubernetes.docker.internal:6443 was refused - did you specify the right host or port?

メリット、デメリット

メリット

デメリット

  • kubectxに比べてクラスタの切り替えが手間となる。
  • 初期設定に少し手間がかかる。

まとめ

 いかがでしょうか?利便性は少し落ちますが、それよりも安全性に重点を置いた仕組みにしました。このあたりはどの方法を選択してもトレードオフになるのではないかと思います。
 この方法で落ち着いてからは、今のところ冷や汗をかいたような場面には遭遇していませんが、もっといい方法がないかというのも模索していますので、もし他にもいい方法があれば是非教えてください。

EKS構築メモ

f:id:cloudfish:20200116173700p:plain:w300
Amazon EKSを触り始めて4ヶ月ほど経ちました。これまでの構築の経験を踏まえてハマった点やこうした方がいいなどの気づいた点や参考になったブログなど、あまりまとまった内容ではありませんがメモとしてまとめておきたいと思います。

VPCのCIDR設計

  EKSのPodのネットワークについては、VPCのネットワークと同じになるネットワーク方式を採用していることから、Podの数だけIPが必要となります。一般的に/24でサブネットを切ることも多いと思いますが、利用可能なIP数は251となるため、システムによってはかなり少ないIPとなりますので、構築するシステムに合わせて余裕を持ったCIDRを設計しておく必要があります。詳細は以下のブログにまとめていますので参照ください。
cloudfish.hatenablog.com

インスタンスタイプの考慮

EC2についても、インスタンスタイプによってEC2にアタッチできるENIの数とENIあたりに割り当て可能なIP数が異なってくるため、どのくらいのPod数が必要になるかある程度見込んだ上で、インスタンスタイプとノード数を決定する必要があります。詳細は上記のブログで説明してます。

EKSクラスタの管理者権限

デフォルトでは、クラスタの管理者権限については、クラスタを作成したIAMユーザー(or ロール)が保持しています。そのため、気づかずに別のユーザーから利用しようとした場合、kubectlコマンドが権限不足でエラーとなります。別のIAMユーザーから利用したい場合はEKSに対してユーザー追加を行う必要がありますので、以下を参照してください。configmapのaws-authを見ても初期ユーザーは登録されていないのですがこれはどこで管理されてるんでしょうね。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html

EC2のロールによるPodのアクセス制御

 サービスアカウントを付与しないPodについてはデフォルトでEC2のロールを通してIAMのアクセス権限を取得します。当初はPodごとにアクセス権限を付与できませんでしたが2019/09のアップデートでPodごとにアクセス権限を付与することが可能になりました。
 これは試してみて分かったのですが、PodにはEC2のロールによるアクセス権限かPod(サービスアカウント)に割り当てたアクセス権限のどちらかしか利用できません。ORの関係ではないので注意が必要です。例えばEC2ロールでS3のアクセス権限があり、PodのサービスアカウントでDynamoDBへのアクセスを許可してPodにサービスアカウントを割り当てた場合、S3へのアクセスはできません。
 基本的にはPodごとにアクセス権限を付与することが望ましいと思いますが、そうできない場合は、全ての権限制御をEC2のロールに寄せるなどした方がいいと思います。中途半端に対応すると作業ミスに繋がるので気をつけてください。

Pod(サービスアカウント)ごとのIAMアクセス制御

当初、他のPodと同じアクセス権限が必要だったのでそれ用のポリシーを作ってそれぞれのPodのサービスアカウントに割り当てていました。
以下のように冗長化を避けるためポリシーを共通化しました。
f:id:cloudfish:20200227165756p:plain:w400

当然のことながら、共通化すると変更時にPod_Aの権限のみ変更したいにも関わらず、Pod_Bにも影響が及ぶことになります。
このため、変更の際の影響範囲や変更ポイントを考慮すると、多少冗長にはなりますが、Pod(=ServiceAccount)とポリシーは1対1で作成した方がいいと思いました。
f:id:cloudfish:20200227170919p:plain:w400

dev.classmethod.jp

ワーカーノードの設定変更

EKSのワーカーノードについては、基本的にイミュータブルとなります。そのため、ノードの設定変更については、ノードグループの再作成を行う必要があります。以前、安易に手作業でノードのセキュリティグループを変更したところ、Podの通信が不安定になったことがありました。原因は手作業で変更したことによるものでした。基本的にはワーカーノードの設定変更はノードグループの再作成を行ってください。Podの通信が不安定になった事象の詳細は以下に掲載しています。
cloudfish.hatenablog.com

リソース制限

Podのリソース(CPU、メモリ)制限を行わないと、Podは必要なだけリソースを使用することになります。当初、あまりこのあたりを気にせずに運用していたところ、ワーカーノードが頻繁にNot Readyとなる問題発生しました。直接的な原因はEBSのDiskのReadが高騰したことになりますが、Readが高騰する原因はノードのメモリの使用率が原因でした。(詳細は以下のブログに書いています。)
cloudfish.hatenablog.com

これに対処するにはkube-reservedとsystem-reservedを設定し、kubernetesの動作に必要なリソースやOSの動作に必要となるリソースを予め確保しておくことでPodに割り当てられるリソースを制限します。設定の詳細については以下が参考になります。
qiita.com
kubernetes.io
eksctl.io

eksctlのハマりポイント

cluster.yamlで設定値が小文字だと認識されないしエラーも出ない

cluster.yamlの設定値はキャメルケースとなっていますが、例えば、「volumeSize」を「volumesize」として表記しeksctlを実行した場合、現状ではエラーも出ずに指定した値で設定されないようなので気をつける必要があります。

クラスター作成時にPolicy指定でAmazonEC2ContainerRegistryReadOnlyは不要

AmazonEC2ContainerRegistryReadOnlyは必ず必要となるポリシーのため、eksctl側で付与されているようです。
そのため、作成時に指定すると以下のようなエラーが出ますので気をつけてください。

[✖] AWS::IAM::Role/NodeInstanceRole: CREATE_FAILED – "Property   ManagedPolicyArns contains duplicate values."

パッと見エラー内容だけでは自分が指定したポリシー内で重複しているわけではなったので原因がすぐには分かりませんでしたが、デフォルトで付与されていますので設定は不要になります。

eksctlのノード追加、削除時のエラー

eksctlでノードグループの追加もしくは削除する際に、以下のようなエラーが出る場合があります。

 getting nodegroup stack summaries: failed to find a nodegroup tag (alpha.eksctl.io/nodegroup-name)

これは作成時のeksctlのバージョンが古い場合で、新しいeksctlで作成した場合に起こります。デバッグログで確認してみると分かるのですが、エラー内容としてはノードグループのCloudFormationに指定されたタグが無いためノードグループが取得できずにエラーになっています。どのバージョンからか分かりませんが、付与されるタグは以下のようになっていました。

 旧:eksctl.io/v1alpha2/nodegroup-name
 新:alpha.eksctl.io/nodegroup-name

対処方法について以下の2通りがあります。

作成時点のeksctlのバージョンで作成する。

Macの場合は以下のコマンドで古いeksctlが取得できます。($versionに取得したいバージョンを設定する必要があります。)

curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/$version/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

今のところ、githubには全てのバージョンが残されているようですが、念の為、クラスターを作ったバージョンのeksctlは残しておいたほうがいいかもしれません。

CloudFormationテンプレートのタグを更新する

「alpha.eksctl.io/nodegroup-name」タグを既存のCloudFormationテンプレートに付与することで対処が可能です。ノードグループが複数ある場合は、全てのCloudFormationテンプレートにタグを付与する必要があります。
タグが正しく設定されていれば、以下のコマンドでノードグループのリストが取得できます。

eksctl get nodegroup --cluster=$CLUSTER_NAME

※ただし、この方法は公式で案内されているわけではないので、テスト環境などでしっかり事前に検証を行ってください。

デプロイ

Kubernetesの便利さはデプロイにあると思います。kubectlコマンドでマニフェストのデプロイも可能ですが、運用面の観点からもツールを使ってデプロイを行った方がいいと思います。ツールはJenkinsX、Spinaker、ArgoCDなど様々なツールがあるので自分に適したツールを選択して利用してください。ちなみに今はArgoCDを使っています。ArgoCDの概要については以下のブログを参照してください、
Argo CDによってGKEでGitOpsをする - Kekeの日記

秘匿情報の管理方法

 デプロイにおいて、DBのパスワードやAPIトークンなどの秘匿情報の管理をどうするかという問題があります。そこで、kubernetesにはsecretという秘匿情報を管理するリソースがあります。ただし、secret自体の定義もマニフェストで管理するとそこに秘匿情報が書かれるのでgitなどにアップしてしまうとセキュリティ上好ましくないことになります。
 より良い方法を模索中ではありますが、現状はAWSのパラメータストアに手動で秘匿情報を登録し、以下のようなコマンドでsecretの登録時にパラメータストアからデータを取得して登録しています。gitにはsecretの登録コマンドをアップすることで秘匿情報を誤ってしてしまうこともありません。

kubectl create -n test secret generic test-secret \
--from-literal=TEST_SECRET=$(aws ssm get-parameter --name test_secret --with-decryption | jq -r .Parameter.Value) \

他にも秘匿情報を管理するためにSealedSecretというツールもありますので参考にしてみてください。
GitOpsでも秘匿情報をバッチリ扱う方法、SealedSecretとは? / How to manage credentials on GitOps - Speaker Deck

※2020/3/5にEKSではKMSをネイティブに使えるようにサポートしました。今後はこれを使う方がいいと思います。
aws.amazon.com

Podが起動しない時のトラブルシューティング

Kubernetesを触り始めた時にPodが立ち上がらなかったりすると、まずどこから調べていいのかよくが分かりませんでした。
そんな時に以下の記事を見つけたのですが、Podのデプロイ時のトラブルシューティングの手順がフローチャートで分かりやすくまとめられていますのでぜひ参考にしてみてください。
learnk8s.io
qiita.com

まとめ

Kubernetesは非常に奥が深いので、まだまだ注意点があると思います。今後運用を続けていく中で気をつける点などEKS特有の問題点などが出てきたら追記していきたいと思います。