Kubernetes Basics
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
架构与基础
Kubernetes 的作用是什么?
- 允许在容器引擎中运行容器。
- 调度使容器任务高效。
- 保持容器存活。
- 允许容器之间的通信。
- 允许部署技术。
- 处理大量信息。
架构

- 节点:带有 pod 或多个 pod 的操作系统。
- Pod:围绕一个或多个容器的包装。一个 pod 应该只包含一个应用程序(因此通常,一个 pod 只运行 1 个容器)。pod 是 Kubernetes 抽象运行容器技术的方式。
- 服务:每个 pod 从节点的内部范围中有 1 个内部 IP 地址。但是,它也可以通过服务暴露。服务也有一个 IP 地址,其目标是维护 pod 之间的通信,因此如果一个 pod 死亡,新的替代品(具有不同的内部 IP)将可访问并暴露在服务的相同 IP 上。可以配置为内部或外部。服务在连接到同一服务的 2 个 pod 时也充当 负载均衡器。
当创建一个 服务 时,可以通过运行kubectl get endpoints找到每个服务的端点。 - Kubelet:主要节点代理。建立节点与 kubectl 之间通信的组件,只能运行 pods(通过 API 服务器)。Kubelet 不管理未由 Kubernetes 创建的容器。
- Kube-proxy:负责 apiserver 和节点之间通信(服务)的服务。基础是节点的 IPtables。经验丰富的用户可以安装来自其他供应商的其他 kube-proxies。
- Sidecar 容器:Sidecar 容器是应该与 pod 中的主容器一起运行的容器。此 sidecar 模式扩展并增强当前容器的功能,而无需更改它们。如今,我们知道我们使用容器技术来包装应用程序在任何地方运行所需的所有依赖项。一个容器只做一件事,并且做得很好。
- 主进程:
- Api 服务器:用户和 pod 用于与主进程通信的方式。只有经过身份验证的请求才应被允许。
- 调度器:调度是指确保 Pods 与节点匹配,以便 Kubelet 可以运行它们。它具有足够的智能来决定哪个节点有更多可用资源并将新 pod 分配给它。请注意,调度器不会启动新 pod,它只是与运行在节点内部的 Kubelet 进程通信,该进程将启动新 pod。
- Kube Controller 管理器:检查资源,如副本集或部署,以检查例如,是否正在运行正确数量的 pods 或节点。如果缺少 pod,它将与调度器通信以启动新的 pod。它控制 API 的复制、令牌和帐户服务。
- etcd:数据存储,持久、一致和分布式。是 Kubernetes 的数据库和键值存储,保存集群的完整状态(每个更改在此记录)。调度器或控制器管理器等组件依赖于此数据以了解发生了哪些更改(节点的可用资源、正在运行的 pod 数量…)。
- Cloud controller manager:是流控制和应用程序的特定控制器,即:如果您在 AWS 或 OpenStack 中有集群。
请注意,由于可能有多个节点(运行多个 pod),因此也可能有多个主进程,它们对 Api 服务器的访问是负载均衡的,并且它们的 etcd 是同步的。
卷:
当 pod 创建的数据在 pod 消失时不应丢失时,应存储在物理卷中。Kubernetes 允许将卷附加到 pod 以持久化数据。卷可以在本地机器上或在 远程存储 中。如果您在不同的物理节点上运行 pods,则应使用远程存储,以便所有 pods 都可以访问它。
其他配置:
- ConfigMap:您可以配置 URLs 以访问服务。pod 将从这里获取数据以了解如何与其余服务(pods)通信。请注意,这不是保存凭据的推荐位置!
- Secret:这是 存储秘密数据 的地方,如密码、API 密钥…以 B64 编码。pod 将能够访问这些数据以使用所需的凭据。
- Deployments:这是指示 Kubernetes 运行的组件的地方。用户通常不会直接与 pods 一起工作,pods 在 ReplicaSets(相同 pods 的数量复制)中被抽象,后者通过部署运行。请注意,部署适用于 无状态 应用程序。部署的最小配置是名称和要运行的镜像。
- StatefulSet:该组件专门用于需要 访问相同存储 的应用程序,如 数据库。
- Ingress:这是用于 通过 URL 公开应用程序 的配置。请注意,这也可以使用外部服务完成,但这是公开应用程序的正确方式。
- 如果您实现了 Ingress,您将需要创建 Ingress Controllers。Ingress Controller 是一个 pod,将是接收请求的端点,并检查并将其负载均衡到服务。Ingress Controller 将 根据配置的 ingress 规则发送请求。请注意,ingress 规则可以指向不同的路径或甚至不同内部 Kubernetes 服务的子域。
- 更好的安全实践是使用云负载均衡器或代理服务器作为入口点,以避免 Kubernetes 集群的任何部分暴露。
- 当收到不匹配任何 ingress 规则的请求时,ingress controller 将其定向到 “默认后端”。您可以
describeingress controller 以获取此参数的地址。 minikube addons enable ingress
PKI 基础设施 - 证书颁发机构 CA:

- CA 是集群中所有证书的受信任根。
- 允许组件相互验证。
- 所有集群证书均由 CA 签名。
- etcd 有自己的证书。
- 类型:
- apiserver 证书。
- kubelet 证书。
- 调度器证书。
基本操作
Minikube
Minikube 可用于在 Kubernetes 上执行一些 快速测试,而无需部署整个 Kubernetes 环境。它将在一台机器上运行 主进程和节点进程。Minikube 将使用 virtualbox 来运行节点。请参见 这里如何安装它。
$ minikube start
😄 minikube v1.19.0 on Ubuntu 20.04
✨ Automatically selected the virtualbox driver. Other choices: none, ssh
💿 Downloading VM boot image ...
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB 100.00% 1.78 MiB p/s 2m17.
👍 Starting control plane node minikube in cluster minikube
💾 Downloading Kubernetes v1.20.2 preload ...
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB 100.00% 2.59 MiB
🔥 Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳 Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul
$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
---- ONCE YOU HAVE A K8 SERVICE RUNNING WITH AN EXTERNAL SERVICE -----
$ minikube service mongo-express-service
(This will open your browser to access the service exposed port)
$ minikube delete
🔥 Deleting "minikube" in virtualbox ...
💀 Removed all traces of the "minikube" cluster
Kubectl 基础
Kubectl 是用于 kubernetes 集群的命令行工具。它与主进程的 Api 服务器通信,以在 kubernetes 中执行操作或请求数据。
kubectl version #Get client and server version
kubectl get pod
kubectl get services
kubectl get deployment
kubectl get replicaset
kubectl get secret
kubectl get all
kubectl get ingress
kubectl get endpoints
#kubectl create deployment <deployment-name> --image=<docker image>
kubectl create deployment nginx-deployment --image=nginx
#Access the configuration of the deployment and modify it
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
#Get the logs of the pod for debbugging (the output of the docker container running)
#kubectl logs <replicaset-id/pod-id>
kubectl logs nginx-deployment-84cd76b964
#kubectl describe pod <pod-id>
kubectl describe pod mongo-depl-5fd6b7d4b4-kkt9q
#kubectl exec -it <pod-id> -- bash
kubectl exec -it mongo-depl-5fd6b7d4b4-kkt9q -- bash
#kubectl describe service <service-name>
kubectl describe service mongodb-service
#kubectl delete deployment <deployment-name>
kubectl delete deployment mongo-depl
#Deploy from config file
kubectl apply -f deployment.yml
Minikube Dashboard
仪表板使您更容易查看 minikube 正在运行的内容,您可以在以下位置找到访问它的 URL:
minikube dashboard --url
🔌 Enabling dashboard ...
▪ Using image kubernetesui/dashboard:v2.3.1
▪ Using image kubernetesui/metrics-scraper:v1.0.7
🤔 Verifying dashboard health ...
🚀 Launching proxy ...
🤔 Verifying proxy health ...
http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
YAML 配置文件示例
每个配置文件有 3 个部分:metadata、specification(需要启动的内容)、status(期望状态)。
在部署配置文件的规范中,您可以找到定义了要运行的映像的新配置结构的模板:
在同一配置文件中声明的 Deployment + Service 示例(来自 这里)
由于服务通常与一个部署相关,因此可以在同一配置文件中声明两者(此配置中声明的服务仅可在内部访问):
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017
外部服务配置示例
该服务将可从外部访问(检查 nodePort 和 type: LoadBlancer 属性):
---
apiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000
Note
这对于测试很有用,但在生产环境中,您应该仅拥有内部服务和一个 Ingress 来公开应用程序。
Ingress 配置文件示例
这将应用程序公开在 http://dashboard.com。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress
namespace: kubernetes-dashboard
spec:
rules:
- host: dashboard.com
http:
paths:
- backend:
serviceName: kubernetes-dashboard
servicePort: 80
示例的秘密配置文件
注意密码是以B64编码的(这并不安全!)
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: dXNlcm5hbWU=
mongo-root-password: cGFzc3dvcmQ=
ConfigMap 示例
一个 ConfigMap 是提供给 pod 的配置,以便它们知道如何定位和访问其他服务。在这种情况下,每个 pod 将知道名称 mongodb-service 是它们可以通信的 pod 的地址(该 pod 将执行 mongodb):
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service
然后,在 deployment config 中,可以通过以下方式指定此地址,以便在 pod 的环境中加载:
[...]
spec:
[...]
template:
[...]
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url
[...]
示例卷配置
您可以在 https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes 找到不同的存储配置 yaml 文件示例。
请注意,卷不在命名空间内
命名空间
Kubernetes 支持 多个虚拟集群,这些集群由同一个物理集群支持。这些虚拟集群称为 命名空间。这些命名空间旨在用于有多个团队或项目的多个用户的环境。对于用户数量从几到几十的集群,您不需要创建或考虑命名空间。您只应在需要更好地控制和组织在 Kubernetes 中部署的应用程序的每个部分时开始使用命名空间。
命名空间为名称提供了作用域。资源的名称在一个命名空间内需要是唯一的,但在不同命名空间之间不需要唯一。命名空间不能相互嵌套,并且 每个 Kubernetes 资源 只能 在 一个 命名空间 中。
如果您使用 minikube,默认情况下有 4 个命名空间:
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-node-lease Active 1d
kube-public Active 1d
kube-system Active 1d
- kube-system: 这不是供用户使用的,您不应该触碰它。它是为 master 和 kubectl 进程准备的。
- kube-public: 公开可访问的数据。包含一个 configmap,其中包含集群信息。
- kube-node-lease: 确定节点的可用性。
- default: 用户将用于创建资源的命名空间。
#Create namespace
kubectl create namespace my-namespace
Note
请注意,大多数 Kubernetes 资源(例如 pods、services、replication controllers 等)位于某些命名空间中。然而,其他资源如命名空间资源和低级资源,如 nodes 和 persistentVolumes 则不在命名空间中。要查看哪些 Kubernetes 资源在命名空间中,哪些不在命名空间中:
kubectl api-resources --namespaced=true #在命名空间中 kubectl api-resources --namespaced=false #不在命名空间中
您可以在该上下文中为所有后续的 kubectl 命令保存命名空间。
kubectl config set-context --current --namespace=<insert-namespace-name-here>
Helm
Helm 是 Kubernetes 的 包管理器。它允许将 YAML 文件打包并在公共和私有仓库中分发。这些包称为 Helm Charts。
helm search <keyword>
Helm 也是一个模板引擎,允许生成带有变量的配置文件:
Kubernetes secrets
一个 Secret 是一个 包含敏感数据 的对象,例如密码、令牌或密钥。这些信息可能会被放在 Pod 规范或镜像中。用户可以创建 Secrets,系统也会创建 Secrets。Secret 对象的名称必须是有效的 DNS 子域名。在这里阅读 the official documentation。
Secrets 可能是以下内容:
- API、SSH 密钥。
- OAuth 令牌。
- 凭据、密码(明文或 b64 + 加密)。
- 信息或注释。
- 数据库连接代码、字符串……。
Kubernetes 中有不同类型的 secrets
| 内置类型 | 用途 |
|---|---|
| Opaque | 任意用户定义的数据(默认) |
| kubernetes.io/service-account-token | 服务账户令牌 |
| kubernetes.io/dockercfg | 序列化的 ~/.dockercfg 文件 |
| kubernetes.io/dockerconfigjson | 序列化的 ~/.docker/config.json 文件 |
| kubernetes.io/basic-auth | 基本身份验证的凭据 |
| kubernetes.io/ssh-auth | SSH 身份验证的凭据 |
| kubernetes.io/tls | TLS 客户端或服务器的数据 |
| bootstrap.kubernetes.io/token | 启动令牌数据 |
Note
Opaque 类型是默认类型,用户定义的典型键值对。
Secrets 的工作原理:

以下配置文件定义了一个名为 mysecret 的 secret,包含 2 个键值对 username: YWRtaW4= 和 password: MWYyZDFlMmU2N2Rm。它还定义了一个名为 secretpod 的 pod,该 pod 将在 环境变量 SECRET_USERNAME __ 和 __ SECRET_PASSWOR 中暴露 mysecret 中定义的 username 和 password。它还将 挂载 mysecret 中的 username secret 到路径 /etc/foo/my-group/my-username,权限为 0640。
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
name: secretpod
spec:
containers:
- name: secretpod
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
volumeMounts:
- name: foo
mountPath: "/etc/foo"
restartPolicy: Never
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
mode: 0640
kubectl apply -f <secretpod.yaml>
kubectl get pods #Wait until the pod secretpod is running
kubectl exec -it secretpod -- bash
env | grep SECRET && cat /etc/foo/my-group/my-username && echo
Secrets in etcd
etcd 是一个一致且高度可用的 键值存储,用于作为 Kubernetes 所有集群数据的后端存储。让我们访问存储在 etcd 中的秘密:
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
您将看到证书、密钥和 URL 位于文件系统中。一旦您获取到这些,您将能够连接到 etcd。
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health
一旦您建立了通信,您将能够获取秘密:
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02
为ETCD添加加密
默认情况下,所有秘密都以明文存储在etcd中,除非您应用加密层。以下示例基于 https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
- identity: {}
之后,您需要在 kube-apiserver 上设置 --encryption-provider-config 标志,以指向创建的配置文件的位置。您可以修改 /etc/kubernetes/manifest/kube-apiserver.yaml 并添加以下行:
containers:
- command:
- kube-apiserver
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
在 volumeMounts 中向下滚动:
- mountPath: /etc/kubernetes/etcd
name: etcd
readOnly: true
向下滚动到 volumeMounts 中的 hostPath:
- hostPath:
path: /etc/kubernetes/etcd
type: DirectoryOrCreate
name: etcd
验证数据是否加密
数据在写入 etcd 时被加密。在重新启动 kube-apiserver 后,任何新创建或更新的秘密在存储时应被加密。要检查,可以使用 etcdctl 命令行程序检索秘密的内容。
- 在
default命名空间中创建一个名为secret1的新秘密:
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
- 使用 etcdctl 命令行,从 etcd 中读取该秘密:
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
其中 [...] 必须是连接到 etcd 服务器的附加参数。
- 验证存储的秘密以
k8s:enc:aescbc:v1:为前缀,这表明aescbc提供程序已加密结果数据。 - 验证通过 API 检索时秘密被正确解密:
kubectl describe secret secret1 -n default
应匹配 mykey: bXlkYXRh,mydata 被编码,检查 decoding a secret 以完全解码秘密。
由于秘密在写入时被加密,对秘密进行更新将加密该内容:
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
最终提示:
- 尽量不要在文件系统中保留秘密,从其他地方获取它们。
- 查看 https://www.vaultproject.io/ 为你的秘密增加更多保护。
- https://kubernetes.io/docs/concepts/configuration/secret/#risks
- https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm
参考
kubesectips v1 | sickrov.github.io
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
HackTricks Cloud

