在 Docker-EE 上使用 Kubernetes 无法从 pod 内标记 Pod
Pod labeling not possible from within pod using Kubernetes on Docker-EE
我们在 Kubernetes 上使用 Apache-Kafka 部署,它基于在创建后标记 pods 的能力(参见 https://github.com/Yolean/kubernetes-kafka)。代理 pods 的初始容器利用此功能在其自身上设置标签,并将其自己的数字索引(例如“0”、“1”等)作为值。该标签在服务描述符中用于 select 恰好一个 pod。
这种方法在我们的 DIND-Kubernetes 环境中运行良好。然而,当试图将部署移植到 Docker-EE Kubernetes 环境时,我们 运行 遇到了麻烦,因为命令 kubectl label pod
生成了一个完全误导的 运行 时间错误(也见 https://github.com/fabric8io/kubernetes-client/issues/853).
为了在最小设置中验证 运行 时间错误,我们创建了以下部署脚本。
第一步:使用 Docker-EE-Host
成功标记 pod
# create a simple pod as a test target for labeling
> kubectl run -ti -n default --image alpine sh
# get the pod name for all further steps
> kubectl -n default get pods
NAME READY STATUS RESTARTS AGE
nfs-provisioner-7d49cdcb4f-8qx95 1/1 Running 1 7d
nginx-deployment-76dcc8c697-ng4kb 1/1 Running 1 7d
nginx-deployment-76dcc8c697-vs24j 1/1 Running 0 20d
sh-777f6db646-hrm65 1/1 Running 0 3m <--- This is the test pod
test-76bbdb4654-9wd9t 1/1 Running 2 6d
test4-76dbf847d5-9qck2 1/1 Running 0 5d
# get client and server versions
> kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.5",
GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean",
BuildDate:"2018-06-21T11:46:00Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"8+", GitVersion:"v1.8.11- docker-8d637ae", GitCommit:"8d637aedf46b9c21dde723e29c645b9f27106fa5",
GitTreeState:"clean", BuildDate:"2018-04-26T16:51:21Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}
# set label
kubectl -n default label pod sh-777f6db646-hrm65 "mylabel=hallo"
pod "sh-777f6db646-hrm65" labeled <---- successful execution
一切正常,如预期。
第二步:从 pod
中重现 运行-time 错误
创建 Docker 图像包含 kubectl
1.10.5
FROM debian:stretch-
slim@sha256:ea42520331a55094b90f6f6663211d4f5a62c5781673935fe17a4dfced777029
ENV KUBERNETES_VERSION=1.10.5
RUN set -ex; \
export DEBIAN_FRONTEND=noninteractive; \
runDeps='curl ca-certificates procps netcat'; \
buildDeps=''; \
apt-get update && apt-get install -y $runDeps $buildDeps --no-install- recommends; \
rm -rf /var/lib/apt/lists/*; \
\
curl -sLS -o k.tar.gz -k https://dl.k8s.io/v${KUBERNETES_VERSION}/kubernetes-client-linux-amd64.tar.gz; \
tar -xvzf k.tar.gz -C /usr/local/bin/ --strip-components=3 kubernetes/client/bin/kubectl; \
rm k.tar.gz; \
\
apt-get purge -y --auto-remove $buildDeps; \
rm /var/log/dpkg.log /var/log/apt/*.log
此映像在站点本地注册表中部署为 10.100.180.74:5000/test/kubectl-client-1.10.5
,将在下面引用。
使用上面的容器创建 pod
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
name: pod-labeler
namespace: default
spec:
selector:
matchLabels:
app: pod-labeler
replicas: 1
serviceName: pod-labeler
updateStrategy:
type: OnDelete
template:
metadata:
labels:
app: pod-labeler
annotations:
spec:
terminationGracePeriodSeconds: 10
containers:
- name: check-version
image: 10.100.180.74:5000/test/kubectl-client-1.10.5
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
value: sh-777f6db646-hrm65
command: ["/usr/local/bin/kubectl", "version" ]
- name: label-pod
image: 10.100.180.74:5000/test/kubectl-client-1.10.5
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
value: sh-777f6db646-hrm65
command: ["/bin/bash", "-c", "/usr/local/bin/kubectl -n default label pod $POD_NAME 'mylabel2=hallo'" ]
记录输出
我们得到以下日志输出
# Log of the container "check-version"
2018-07-18T11:11:10.791011157Z Client Version: version.Info{Major:"1",
Minor:"10", GitVersion:"v1.10.5",
GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean",
BuildDate:"2018-\
06-21T11:46:00Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
2018-07-18T11:11:10.791058997Z Server Version: version.Info{Major:"1",
Minor:"8+", GitVersion:"v1.8.11-docker-8d637ae",
GitCommit:"8d637aedf46b9c21dde723e29c645b9f27106fa5", GitTreeState:"clean",
BuildDate:"2018-04-26T16:51:21Z", GoVersion:"go1.8.3", Compiler:"gc",
Platform:"linux/amd64"}
和运行时间错误
2018-07-18T11:24:15.448695813Z The Pod "sh-777f6db646-hrm65" is invalid:
spec.tolerations: Forbidden: existing toleration can not be modified except its tolerationSeconds
备注
- 这不是授权问题,因为我们已经为默认命名空间的默认用户授予了完全管理权限。如果我们不这样做,我们会收到一条错误消息,指出缺少权限。
- 客户端和服务器版本 "outside"(例如在 docker 主机上)和 "inside"(例如 pod)在 GIT 提交标签下都是相同的
- 我们正在使用 Universal Control Plane 的 3.0.2 版
有什么想法吗?
其中一条评论指出,问题可能是由缺少权限引起的,即使错误消息并未暗示如此。我们正式提交了一张 Docker 的票证,实际上得到了这个结果:为了能够 set/modify 来自 pod 的标签,必须为命名空间的默认用户提供 "Scheduler" swarm 资源上的角色(稍后在 GUI 中显示为 \
)。授予此权限可以解决问题。请参阅下面 Docker-EE-GUI 中添加的授权。
在我看来,这远非显而易见。 Docker 支持代表主动提出调查这是否确实是预期的行为或错误的结果。一旦我们了解有关此问题的更多信息,我会将其包含在我们的回答中。
至于使用更多的调试输出:不幸的是,将 --v=9
添加到 kubectl
的调用中并没有 return 任何有用的信息。这里要显示的输出太多,但两种情况下的整体日志记录非常相似:它由很多 GET API 请求组成,这些请求全部成功,然后是最终的 PATCH API 请求,该请求在如上所述,一种情况在另一种情况下失败。
我们在 Kubernetes 上使用 Apache-Kafka 部署,它基于在创建后标记 pods 的能力(参见 https://github.com/Yolean/kubernetes-kafka)。代理 pods 的初始容器利用此功能在其自身上设置标签,并将其自己的数字索引(例如“0”、“1”等)作为值。该标签在服务描述符中用于 select 恰好一个 pod。
这种方法在我们的 DIND-Kubernetes 环境中运行良好。然而,当试图将部署移植到 Docker-EE Kubernetes 环境时,我们 运行 遇到了麻烦,因为命令 kubectl label pod
生成了一个完全误导的 运行 时间错误(也见 https://github.com/fabric8io/kubernetes-client/issues/853).
为了在最小设置中验证 运行 时间错误,我们创建了以下部署脚本。
第一步:使用 Docker-EE-Host
成功标记 pod# create a simple pod as a test target for labeling
> kubectl run -ti -n default --image alpine sh
# get the pod name for all further steps
> kubectl -n default get pods
NAME READY STATUS RESTARTS AGE
nfs-provisioner-7d49cdcb4f-8qx95 1/1 Running 1 7d
nginx-deployment-76dcc8c697-ng4kb 1/1 Running 1 7d
nginx-deployment-76dcc8c697-vs24j 1/1 Running 0 20d
sh-777f6db646-hrm65 1/1 Running 0 3m <--- This is the test pod
test-76bbdb4654-9wd9t 1/1 Running 2 6d
test4-76dbf847d5-9qck2 1/1 Running 0 5d
# get client and server versions
> kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.5",
GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean",
BuildDate:"2018-06-21T11:46:00Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"8+", GitVersion:"v1.8.11- docker-8d637ae", GitCommit:"8d637aedf46b9c21dde723e29c645b9f27106fa5",
GitTreeState:"clean", BuildDate:"2018-04-26T16:51:21Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}
# set label
kubectl -n default label pod sh-777f6db646-hrm65 "mylabel=hallo"
pod "sh-777f6db646-hrm65" labeled <---- successful execution
一切正常,如预期。
第二步:从 pod
中重现 运行-time 错误创建 Docker 图像包含 kubectl
1.10.5
FROM debian:stretch-
slim@sha256:ea42520331a55094b90f6f6663211d4f5a62c5781673935fe17a4dfced777029
ENV KUBERNETES_VERSION=1.10.5
RUN set -ex; \
export DEBIAN_FRONTEND=noninteractive; \
runDeps='curl ca-certificates procps netcat'; \
buildDeps=''; \
apt-get update && apt-get install -y $runDeps $buildDeps --no-install- recommends; \
rm -rf /var/lib/apt/lists/*; \
\
curl -sLS -o k.tar.gz -k https://dl.k8s.io/v${KUBERNETES_VERSION}/kubernetes-client-linux-amd64.tar.gz; \
tar -xvzf k.tar.gz -C /usr/local/bin/ --strip-components=3 kubernetes/client/bin/kubectl; \
rm k.tar.gz; \
\
apt-get purge -y --auto-remove $buildDeps; \
rm /var/log/dpkg.log /var/log/apt/*.log
此映像在站点本地注册表中部署为 10.100.180.74:5000/test/kubectl-client-1.10.5
,将在下面引用。
使用上面的容器创建 pod
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
name: pod-labeler
namespace: default
spec:
selector:
matchLabels:
app: pod-labeler
replicas: 1
serviceName: pod-labeler
updateStrategy:
type: OnDelete
template:
metadata:
labels:
app: pod-labeler
annotations:
spec:
terminationGracePeriodSeconds: 10
containers:
- name: check-version
image: 10.100.180.74:5000/test/kubectl-client-1.10.5
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
value: sh-777f6db646-hrm65
command: ["/usr/local/bin/kubectl", "version" ]
- name: label-pod
image: 10.100.180.74:5000/test/kubectl-client-1.10.5
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
value: sh-777f6db646-hrm65
command: ["/bin/bash", "-c", "/usr/local/bin/kubectl -n default label pod $POD_NAME 'mylabel2=hallo'" ]
记录输出
我们得到以下日志输出
# Log of the container "check-version"
2018-07-18T11:11:10.791011157Z Client Version: version.Info{Major:"1",
Minor:"10", GitVersion:"v1.10.5",
GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean",
BuildDate:"2018-\
06-21T11:46:00Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
2018-07-18T11:11:10.791058997Z Server Version: version.Info{Major:"1",
Minor:"8+", GitVersion:"v1.8.11-docker-8d637ae",
GitCommit:"8d637aedf46b9c21dde723e29c645b9f27106fa5", GitTreeState:"clean",
BuildDate:"2018-04-26T16:51:21Z", GoVersion:"go1.8.3", Compiler:"gc",
Platform:"linux/amd64"}
和运行时间错误
2018-07-18T11:24:15.448695813Z The Pod "sh-777f6db646-hrm65" is invalid:
spec.tolerations: Forbidden: existing toleration can not be modified except its tolerationSeconds
备注
- 这不是授权问题,因为我们已经为默认命名空间的默认用户授予了完全管理权限。如果我们不这样做,我们会收到一条错误消息,指出缺少权限。
- 客户端和服务器版本 "outside"(例如在 docker 主机上)和 "inside"(例如 pod)在 GIT 提交标签下都是相同的
- 我们正在使用 Universal Control Plane 的 3.0.2 版
有什么想法吗?
其中一条评论指出,问题可能是由缺少权限引起的,即使错误消息并未暗示如此。我们正式提交了一张 Docker 的票证,实际上得到了这个结果:为了能够 set/modify 来自 pod 的标签,必须为命名空间的默认用户提供 "Scheduler" swarm 资源上的角色(稍后在 GUI 中显示为 \
)。授予此权限可以解决问题。请参阅下面 Docker-EE-GUI 中添加的授权。
在我看来,这远非显而易见。 Docker 支持代表主动提出调查这是否确实是预期的行为或错误的结果。一旦我们了解有关此问题的更多信息,我会将其包含在我们的回答中。
至于使用更多的调试输出:不幸的是,将 --v=9
添加到 kubectl
的调用中并没有 return 任何有用的信息。这里要显示的输出太多,但两种情况下的整体日志记录非常相似:它由很多 GET API 请求组成,这些请求全部成功,然后是最终的 PATCH API 请求,该请求在如上所述,一种情况在另一种情况下失败。