AWS re:Postを使用することにより、以下に同意したことになります 利用規約

ユーザーデータを持つ EKS ワーカーノードの HTTP プロキシ設定を自動化するにはどうすればよいですか?

所要時間4分
0

ユーザーデータを持つ Amazon Elastic Kubernetes Service (Amazon EKS) ワーカーノードの HTTP プロキシ設定を自動化したいと考えています。

簡単な説明

ワーカーノードでプロキシを設定するには、Amazon EKS クラスターの必要なコンポーネントを、プロキシ経由で通信するように設定する必要があります。コンポーネントには、kubelet systemd サービス、kube-proxy、aws-node ポッド、および yum 更新が含まれますが、これらに限られません。 Docker ランタイムでワーカーノードのプロキシ設定を自動化するには、以下を実行します。 

注: 次の解決方法は、基盤となるランタイムが Docker であるノードにのみ適用され、containerd ランタイムのノードには適用されません。containerd ランタイムを使用するノードについては、「How can I automate the configuration of HTTP proxy for EKS containerd nodes?」(EKS containerd ノードの HTTP プロキシの設定を自動化するにはどうすればよいですか?) を参照してください。

解決方法

1.クラスターの IP CIDR ブロックを見つけます。

$ kubectl get service kubernetes -o jsonpath='{.spec.clusterIP}'; echo

前述のコマンドは10.100.0.1 または 172.20.0.1 のいずれかを返します。つまり、クラスターの IP CIDR ブロックは 10.100.0.0/16 または 172.20.0.0/16 のいずれかになります。

2.ステップ 1 のコマンドの出力に基づいて、proxy-env-vars-config.yaml という名前の ConfigMap ファイルを作成します。

出力に 172.20.x.x の範囲の IP がある場合は、次のように ConfigMap ファイルを構成してください。

apiVersion: v1
kind: ConfigMap
metadata:
 name: proxy-environment-variables
 namespace: kube-system
data:
 HTTP_PROXY: http://customer.proxy.host:proxy_port
 HTTPS_PROXY: http://customer.proxy.host:proxy_port
 NO_PROXY: 172.20.0.0/16,localhost,127.0.0.1,VPC_CIDR_RANGE,169.254.169.254,.internal,s3.amazonaws.com,.s3.us-east-1.amazonaws.com,api.ecr.us-east-1.amazonaws.com,dkr.ecr.us-east-1.amazonaws.com,ec2.us-east-1.amazonaws.com

注: VPC_CIDR_RANGE をクラスターの VPC の IPv4 CIDR ブロックに置き換えます。

出力に 10.100.x.x の範囲の IP がある場合は、次のように ConfigMap ファイルを構成してください。

apiVersion: v1
kind: ConfigMap
metadata:
 name: proxy-environment-variables
 namespace: kube-system
data:
 HTTP_PROXY: http://customer.proxy.host:proxy_port
 HTTPS_PROXY: http://customer.proxy.host:proxy_port
 NO_PROXY: 10.100.0.0/16,localhost,127.0.0.1,VPC_CIDR_RANGE,169.254.169.254,.internal,s3.amazonaws.com,.s3.us-east-1.amazonaws.com,api.ecr.us-east-1.amazonaws.com,dkr.ecr.us-east-1.amazonaws.com,ec2.us-east-1.amazonaws.com

注: VPC_CIDR_RANGE をクラスターの VPC の IPv4 CIDR ブロックに置き換えます。

プライベート API サーバーエンドポイントアクセスとプライベートサブネットがあり、インターネットアクセスがない Amazon EKS クラスターには、追加のエンドポイントが必要です。前述の設定でクラスターを構築する場合は、次のサービス用にエンドポイントを作成および追加する必要があります。

  • Amazon Elastic Container Registry (Amazon ECR)
  • Amazon Simple Storage Service (Amazon S3)
  • Amazon Elastic Compute Cloud (Amazon EC2)
  • Amazon Virtual Private Cloud (Amazon VPC)

例えば、api.ecr.us-east-1.amazonaws.comdkr.ecr.us-east-1.amazonaws.coms3.amazonaws.coms3.us-east-1.amazonaws.comec2.us-east-1.amazonaws.com といったエンドポイントを使用できます。

重要: パブリックエンドポイントサブドメインを NO_PROXY 変数に追加する必要があります。例えば、Amazon S3 の .s3.us-east-1.amazonaws.com ドメインを us-east-1 AWS リージョンで追加します。Amazon EKS クラスターのエンドポイントプライベートアクセスを有効にした場合は、NO_PROXY 変数に Amazon EKS エンドポイントを追加する必要があります。例えば、us-east-1 の AWS リージョンの Amazon EKS クラスターの .us-east-1.eks.amazonaws.com ドメインを追加します。

3.(kube-proxy および aws-node ポッドで使用されている) configmap/proxy-environment-variables にある NO_PROXY 変数に Kubernetes クラスターの IP アドレス空間が含まれていることを確認します。例えば、IP 範囲が 10.100.x.x からの ConfigMap ファイルの前述のコードサンプルでは、10.100.0.0/16 が使用されます。

4.ConfigMap を適用します。

$ kubectl apply -f /path/to/yaml/proxy-env-vars-config.yaml

5.Docker デーモンと kubelet を設定するには、ワーカーノードにユーザーデータを投入します。例:

Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version:  1.0

--==BOUNDARY==
Content-Type: text/cloud-boothook; charset="us-ascii"

#Set the proxy hostname and port
PROXY="proxy.local:3128"
MAC=$(curl -s http://169.254.169.254/latest/meta-data/mac/)
VPC_CIDR=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/vpc-ipv4-cidr-blocks | xargs | tr ' ' ',')

#Create the docker systemd directory
mkdir -p /etc/systemd/system/docker.service.d

#Configure yum to use the proxy
cloud-init-per instance yum_proxy_config cat << EOF >> /etc/yum.conf
proxy=http://$PROXY
EOF

#Set the proxy for future processes, and use as an include file
cloud-init-per instance proxy_config cat << EOF >> /etc/environment
http_proxy=http://$PROXY
https_proxy=http://$PROXY
HTTP_PROXY=http://$PROXY
HTTPS_PROXY=http://$PROXY
no_proxy=$VPC_CIDR,localhost,127.0.0.1,169.254.169.254,.internal,s3.amazonaws.com,.s3.us-east-1.amazonaws.com,api.ecr.us-east-1.amazonaws.com,dkr.ecr.us-east-1.amazonaws.com,ec2.us-east-1.amazonaws.com
NO_PROXY=$VPC_CIDR,localhost,127.0.0.1,169.254.169.254,.internal,s3.amazonaws.com,.s3.us-east-1.amazonaws.com,api.ecr.us-east-1.amazonaws.com,dkr.ecr.us-east-1.amazonaws.com,ec2.us-east-1.amazonaws.com
EOF

#Configure docker with the proxy
cloud-init-per instance docker_proxy_config tee <<EOF /etc/systemd/system/docker.service.d/proxy.conf >/dev/null
[Service]
EnvironmentFile=/etc/environment
EOF

#Configure the kubelet with the proxy
cloud-init-per instance kubelet_proxy_config tee <<EOF /etc/systemd/system/kubelet.service.d/proxy.conf >/dev/null
[Service]
EnvironmentFile=/etc/environment
EOF

#Reload the daemon and restart docker to reflect proxy configuration at launch of instance
cloud-init-per instance reload_daemon systemctl daemon-reload 
cloud-init-per instance enable_docker systemctl enable --now --no-block docker

--==BOUNDARY==
Content-Type:text/x-shellscript; charset="us-ascii"

#!/bin/bash
set -o xtrace

#Set the proxy variables before running the bootstrap.sh script
set -a
source /etc/environment

/etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments}

# Use the cfn-signal only if the node is created through an AWS CloudFormation stack and needs to signal back to an AWS CloudFormation resource (CFN_RESOURCE_LOGICAL_NAME) that waits for a signal from this EC2 instance to progress through either:
# - CreationPolicy https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html
# - UpdatePolicy https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html
# cfn-signal will signal back to AWS CloudFormation using https transport, so set the proxy for an HTTPS connection to AWS CloudFormation
/opt/aws/bin/cfn-signal
    --exit-code $? \
    --stack  ${AWS::StackName} \
    --resource CFN_RESOURCE_LOGICAL_NAME  \
    --region ${AWS::Region} \
    --https-proxy $HTTPS_PROXY

--==BOUNDARY==--

重要: Docker デーモンと kubelet を起動する前に、yumDocker、および kubelet の設定ファイルを更新または作成する必要があります。

AWS CloudFormation テンプレートを使用してワーカーノードに挿入されたユーザーデータの例については、「セルフマネージド型の Amazon Linux ノードの起動」を参照してください。

6.aws-node および kube-proxy ポッドを更新します。

$ kubectl patch -n kube-system -p '{ "spec": {"template": { "spec": { "containers": [ { "name": "aws-node", "envFrom": [ { "configMapRef": {"name": "proxy-environment-variables"} } ] } ] } } } }' daemonset aws-node
$ kubectl patch -n kube-system -p '{ "spec": {"template":{ "spec": { "containers": [ { "name": "kube-proxy", "envFrom": [ { "configMapRef": {"name": "proxy-environment-variables"} } ] } ] } } } }' daemonset kube-proxy

ConfigMap を変更した場合は、更新を適用し、ポッドに ConfigMap を再度設定します。例:

$ kubectl set env daemonset/kube-proxy --namespace=kube-system --from=configmap/proxy-environment-variables --containers='*'
$ kubectl set env daemonset/aws-node --namespace=kube-system --from=configmap/proxy-environment-variables --containers='*'

重要: これらのオブジェクトをアップグレードする場合は、kubernetes オブジェクト kube-proxy または aws-node に対するすべての YAML 変更を更新する必要があります。ConfigMap をデフォルト値に更新するには、eksctl utils update-kube-proxy または eksctl utils update-aws-node コマンドを使用します。

ヒント: プロキシが API サーバーに接続できなくなった場合、プロキシは単一障害点になり、クラスターの動作が予測不能になる可能性があります。プロキシが単一障害点にならないようにするには、サービス検出名前空間またはロードバランサーの背後でプロキシを実行します。

7.プロキシ変数が kube-proxy および aws-node ポッドで使用されていることを確認します。

$ kubectl describe pod kube-proxy-xxxx -n kube-system

出力は次のようになります。

Environment:
 HTTPS_PROXY: <set to the key 'HTTPS_PROXY' of config map 'proxy-environment-variables'> Optional: false
 HTTP_PROXY: <set to the key 'HTTP_PROXY' of config map 'proxy-environment-variables'> Optional: false
 NO_PROXY: <set to the key 'NO_PROXY' of config map 'proxy-environment-variables'> Optional: false

AWS PrivateLink を使用していない場合は、Amazon EC2、Amazon ECR、および Amazon S3 のプロキシサーバー経由で API エンドポイントへのアクセスを検証します。


AWS公式
AWS公式更新しました 2ヶ月前