IAM是AWS的实际的受权方法。大部分针对AWS的Kubernetes的“快速入门”指南并无充分覆盖如何在你的Pod中管理IAM访问的相关内容。本系列文章讲探讨Kubernetes环境的AWS IAM特有的安全性问题,而后对比不一样方案,并最终详细介绍如何选择一种方案来设置集群。node
在以前的文章中,咱们在生产kubernetes集群中安装了kiam。在本文中,咱们将介绍在成产环境快速安装kube2iam的过程.git
本文将包含你在身缠环境部署kube2iamd的如下4步:github
浏览kube2iam概况及特性,请查看 Github Page。docker
使用kubeiam的第一步是为你的Pod建立IAM roles。kube2iam的工做方式是须要一个IAM策略附加到集群中每一个节点以容许其为Pod委派roles。json
建立为你的节点一个IAM策略而且附加到你的kubernetes节点的role上。api
策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Resource": "*" } ] }
接下来为每一个pod建立role。每一个role将须要一个策略,拥有Pod功能所需的最小权限,例如:列出S3对象,写入DynamoDB, 读取SQS等。你须要为每一个所建立的role更新委派角色策略,以便使你的节点能够委派这些role。用kubernetes节点所附加role的arn
替换YOUR_NODE_ROLE
。安全
委派角色策略:
{ "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ec2.amazonaws.com" }, "Effect": "Allow", "Sid": "" }, { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "YOUR_NODE_ROLE" }, "Action": "sts:AssumeRole" } ] }
pod
增长Annotations
下一步将你的pod将用的role注释到Pod。增长一个annotation
到pod 的metadata.spec
便可,kube2iam使用IAM对Pod进行身份认证时将使用这个role。如此配置后,kube2iam将为该role自动检查基础arn
,可是若是你须要委派角色给其余AWS帐号也能够指定一个完整的arn
(以arn:aws:iam
开始)。kube2iam文档有一些不一样pod控制器的例子。网络
annotations: iam.amazonaws.com/role: MY_ROLE_NAME
如今能够部署kube2iam。你能够参考kube2iam github repo 获取EKS和OpenShift的例子,可是这里也也会介绍一些通用deployment方法。第一步时配置RBAC:app
--- apiVersion: v1 kind: ServiceAccount metadata: name: kube2iam namespace: kube-system --- apiVersion: v1 items: - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kube2iam rules: - apiGroups: [""] resources: ["namespaces","pods"] verbs: ["get","watch","list"] - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube2iam subjects: - kind: ServiceAccount name: kube2iam namespace: kube-system roleRef: kind: ClusterRole name: kube2iam apiGroup: rbac.authorization.k8s.io kind: List
由于kube2iam修改了kubernetes节点上的iptables规则来劫持到EC2 metadata服务的流量,我建议增长一个tainted
的新节点到集群,这样你能够在确保不影响你生产环境Pod的前提下测试控制器来配置正确。为集群增长一个节点而后为其打上五点钟,这样其余Pod就不会被调度到该节点。tcp
export ALICLOUD_ACCOUNT="" export ALICLOUD_ACCESS_KEY="your-access-key" export ALICLOUD_SECRET_KEY="your-secret-key" export ALICLOUD_REGION="cn-qingdao"
kubectl taint nodes NODE_NAME kube2iam=kube2iam:NoSchedule
接下来咱们能够在该节点上配置agent。增长nodeName: NEW_NODE_NAME
到Pod.spec
,而后增长tolerations
这样它就能够被调度到该节点。设置镜像版本为标记过的发布版本而非latest
。还须要设置--host-interface
命令参数来适配你的CNI
。kube2iam页面有完整的支持列表。我也建议设置 --auto-discover-base-arn
和 --auto-discover-default-role
参数来时配置和迁移更容易。若是你的集群再单个可用区--use-regional-sts-endpoint
会颇有用,可是你必须为其设置 AWS_REGION
环境变量。综上所述,配置大体以下:
apiVersion: apps/v1 kind: DaemonSet metadata: name: kube2iam namespace: kube-system labels: app: kube2iam spec: selector: matchLabels: name: kube2iam template: metadata: labels: name: kube2iam spec: nodeName: NEW_NODE_NAME tolerations: - key: kube2iam value: kube2iam effect: NoSchedule serviceAccountName: kube2iam hostNetwork: true containers: - image: jtblin/kube2iam:0.10.6 imagePullPolicy: Always name: kube2iam args: - "--app-port=8181" - "--auto-discover-base-arn" - "--iptables=true" - "--host-ip=$(HOST_IP)" - "--host-interface=weave" - "--use-regional-sts-endpoint" - "--auto-discover-default-role" - "--log-level=info" env: - name: HOST_IP valueFrom: fieldRef: fieldPath: status.podIP - name: AWS_REGION value: "us-east-1" ports: - containerPort: 8181 hostPort: 8181 name: http securityContext: privileged: true
接下来你能够建立agent并确认该agent运行于你的新节点上。你其余节点上的Pod不会有变动。
在这一步,开始测试以指望一切正常。你能够经过在该隔离节点部署一个Pod,而后在该POD中使用AWS CLI访问资源进行测试。当你作这些时,请检查kube2iam agent的日志来debug你遇到的的问题。这里有个deployment实例,你能够指定一个role而后用它进行访问测试。
apiVersion: apps/v1beta2 kind: Deployment metadata: name: aws-iam-tester labels: app: aws-iam-tester spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: aws-iam-tester template: metadata: labels: app: aws-iam-tester annotations: iam.amazonaws.com/role: TEST_ROLE_NAME spec: nodeSelector: kubernetes.io/role: node nodeName: NEW_NODE_NAME tolerations: - key: kube2iam value: kube2iam effect: NoSchedule containers: - name: aws-iam-tester image: garland/aws-cli-docker:latest imagePullPolicy: Always command: - /bin/sleep args: - "3600" env: - name: AWS_DEFAULT_REGION value: us-east-1
Pod将会在一个小时后退出,你可使用kubectl获取一个TTY到Pod。
kubectl exec -ti POD_NAME /bin/sh
一旦你确认你的role能够正常工做,而且kube2iam agent配置正常,你就能够部署agent到每一个节点。
从kube2iam Daemonset删除nodeName
和kub2iam:kub2iam
以容许它运行到每一个节点。 在每一个节点安装完成之后,应该对关键pod进行更新,以这些Pod当即使用kube2iam进行验证。其余曾经使用node role进行认证的的Pod当其临时凭据过时后将开始使用kube2iam进行认证(一般是一个小时)。若IAM认证有错,请检查你的应用及kubeiam日志。
当一切运行正常,你就能够删除再次以前添加的隔离节点。
遇到问题时,你能够删除全部节点上的agent,可是它不会自动清理它建立的iptable规则。这将致使全部发往EC2 metada的请求不起做用。你须要分别登陆到每一个节点并手动移除这些iptables规则。
首先列出iptable规则,找出kube2iam所建立的部分
sudo iptables -t nat -S PREROUTING | grep 169.254.169.254
输出大概以下:
-A PREROUTING -d 169.254.169.254/32 -i weave -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.101.101:8181
若是你意外的使用不一样的--host-interface
选项部署agent你可能会看到多个结果。你能够一次删除他们。删除一条规则使用iptables的-D
选项并指定-A
选项输出的具体行号,例如:
sudo iptables -t nat -D PREROUTING -d 169.254.169.254/32 -i weave -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.101.101:8181
当每一个节点上都执行事后,EC2 metadta请求将不在发往kube2iam.
如今有kube2iam运行于你的生产集群以及,并为POD建立独立的角色。
若是你的对其余阿方案看兴趣,请查看我以前写的[kiam安装]()一文。它更加复杂,而且使用不一样的方法解决IAM的问题。我也在关注 kube-aws-iam-controller做为替代方案,可是该项目一直不太成熟不适合生产环境。你可也能够查看本系列第一,第二篇文章来了解kubernetes中使用AWS IAM的问题,以及对kiam和kube2iam做为解决方案的深刻比较。
因在下英文太烂,若是能够您阅读英文,强烈建议 查看原文
Question: Add support for Instance Metadata Service Version 2 (IMDSv2)Question: 注意你的集群所使用的网络方案,好比:文中例子为
weave
,个人集群为Calico
,因此应该修改成cali+
。不然会报以下错误:
$ k logs kube2iam-ltm7f -n kube-system ... time="2020-07-17T10:47:30Z" level=fatal msg="route ip+net: no such network interface"
Question 2: 默认状况下kube2iam使用8181端口,由于个人worker node使用了8181端口,须要增长2个参数
--app-port=8182 --metrics-port=8183
,不然会报以下错误:
$ k logs kube2iam-bk59z -n kube-system time="2020-07-18T03:42:04Z" level=info msg="Listening on port 8181" time="2020-07-18T03:42:04Z" level=fatal msg="Error creating kube2iam http server: listen tcp :8181: bind: address already in use"
Question 3: 使用文中命令未找到相应的iptables规则
$ sudo iptables -t nat -S PREFOUTING | grep 169.254.169.254 iptables: No chain/target/match by that name. # 尝试以下命令 sudo iptables -t nat -L | grep 169.254.169.254