跳至内容

如何使用 Docker 自动配置 Amazon EKS Worker 节点的 HTTP 代理?

4 分钟阅读
0

我想使用用户数据自动配置 Amazon Elastic Kubernetes Service (Amazon EKS) Worker 节点的 HTTP 代理。

解决方法

**注意:**以下解决方法仅适用于底层运行时为 Docker 的节点,不适用于使用 containerd 运行时的节点。对于使用 containerd 运行时的节点,请参阅如何自动配置 Amazon EKS containerd 节点的 HTTP 代理?

要在 Worker 节点上设置代理,您必须配置 Amazon EKS 集群的必要组件,以便通过代理进行通信。组件包括 kubelet systemd 服务、kube-proxy、aws-node 容器组 (pod) 和 yum 更新。

要使用 Docker 运行时自动为 Worker 节点配置代理,请完成以下步骤:

  1. 查找集群的 IP 地址 CIDR 块:

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

    **注意:**上述命令返回 10.100.0.1172.20.0.1,因此集群 IP 地址 CIDR 块为 10.100.0.0/16172.20.0.0/16

  2. 根据命令的输出,创建一个名为 proxy-env-vars-config.yaml 的 ConfigMap 文件。
    如果输出的 IP 地址范围始于 172.20.x.x,则使用以下 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 块。
    如果输出的 IP 地址范围始于 10.100.x.x,则使用以下 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)
    **重要事项:**您必须将公共端点子域添加到 NO_PROXY 变量。例如,在 us-east-1 AWS 区域为 Amazon S3 添加 .s3.us-east-1.amazonaws.com 域。如果您为 Amazon EKS 集群启用端点私有访问,则必须将 Amazon EKS 端点添加到 NO_PROXY 变量。例如,在 us-east-1 AWS 区域为您的 Amazon EKS 集群添加 .us-east-1.eks.amazonaws.com 域。

  3. 验证 kube-proxyaws-node 容器组 (pod) 使用的 configmap/proxy-environment-variables 中的 NO_PROXY 变量是否包含 Kubernetes 集群 IP 地址空间。例如,在 ConfigMap 文件的上述代码示例中使用了 10.100.0.0/16,其中 IP 地址范围始于 10.100.x.x

  4. 应用 ConfigMap:

    $ kubectl apply -f /path/to/yaml/proxy-env-vars-config.yaml
  5. 要配置 Docker 进程守护程序和 kubelet,请在您的 Worker 节点中添加用户数据:

    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 之前,您必须更新或创建 yum、Docker 和 kubelet 配置文件。
    有关如何使用 AWS CloudFormation 模板在 Worker 节点中添加用户数据的更多信息,请参阅创建自行管理的 Amazon Linux 节点

  6. 要更新 aws-nodekube-proxy 容器组 (pod),请运行以下命令:

    $ 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,请应用更新,然后再次在容器组 (pod) 中设置 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='*'

    **重要事项:**更新 kube-proxyaws-node 时,还必须更新所有 YAML 修改。要将 ConfigMap 更新为默认值,请运行 eksctl utils update-kube-proxyeksctl utils update-aws-node 命令。
    如果代理与 API 服务器断开连接,则代理会成为单点故障,并可能导致集群行为不可预测。为防止出现此问题,请在服务发现命名空间或负载均衡器后面运行代理。

  7. 检查是否在 kube-proxyaws-node 容器组 (pod) 中使用了代理变量:

    $ 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

    如果您没有使用 AWS PrivateLink,请通过 Amazon EC2、Amazon ECR 和 Amazon S3 的代理服务器验证对 API 端点的访问权限。

AWS 官方已更新 1 年前