本教程还介绍了如何将 kpt 与其他 Google 解决方案(如 Config Sync 和 GKE Enterprise 安全蓝图)结合使用。无论您是与 Kubernetes 合作的开发者,还是管理基于 Kubernetes 的平台的平台工程师,本教程都可以让您了解如何在您自己的 Kubernetes 相关工作流中使用 kpt。本教程假定您熟悉 Kubernetes 和 Google Cloud。
云基础架构的声明式配置是 IT 行业中确立的良好做法。它引入了底层系统的强大抽象结构。这种抽象使您不必管理底层配置细节和依赖项。因此,与命令式方法(例如在图形和命令行界面中执行的操作)相比,声明式配置具有优势。
Kubernetes 资源模型在使声明式配置方法成为主流方面发挥着重要作用。因为 Kubernetes API 本质上是完全声明性的,所以您只需告诉 Kubernetes 您想要什么,而不是如何实现您想要的。Kubernetes API 使您可以将配置(无论是期望的还是实际的)与配置操作(添加、移除和修改对象)完全分开。换句话说,在 Kubernetes 资源模型中,配置是数据,而不是代码。
配置与操作的这种分离具有许多优点:人员和自动化系统可以理解和使用配置,并且修改配置的软件易于重复使用。此分离也可让您轻松实现 GitOps 方法(如使用 Cloud Build 实现 GitOps 形式的持续交付教程中所述)。
在本教程中,您将使用 kpt 探索配置声明与配置操作的分离。本教程重点介绍了 kpt 的以下功能:
- 软件包管理:下载和更新 Kubernetes 配置软件包。
- 函数:运行任意一段代码以修改或验证您的配置。
- 函数流水线:软件包作者包含在软件包中的一组函数。
- 资源管理:应用、更新和删除与 Kubernetes 集群中配置对应的资源。
目标
- 创建 Google Kubernetes Engine (GKE) 集群。
- 使用 kpt 下载一组现有的 Kubernetes 配置。
- 使用 kpt 函数自定义配置。
- 将您的配置应用到 GKE 集群。
- 使用 kpt 拉取配置的一些上游更改。
- 在实际场景中使用 kpt 强化 GKE 集群。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
- Google Kubernetes Engine
准备工作
- 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
在 Google Cloud 控制台中,激活 Cloud Shell。
Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。
将 Cloud Shell 配置为使用您的项目:
gcloud config set project PROJECT_ID
-
在 Cloud Shell 中,启用 Google Kubernetes Engine 和 Cloud Source Repositories API:
gcloud services enable container.googleapis.com \ sourcerepo.googleapis.com
完成本教程后,您可以通过删除您创建的资源来避免继续计费。如需了解详情,请参阅清理。
创建 GKE 集群
在本部分中,您将创建 GKE 集群,以便在本教程的后面部分中部署配置。
在 Cloud Shell 中创建一个 GKE 集群:
gcloud container clusters create kpt-tutorial \ --num-nodes=1 --machine-type=n1-standard-4 \ --zone=us-central1-a --enable-network-policy
验证您有权访问该集群。以下命令返回有关集群中一个或多个节点的信息。
kubectl get nodes
应用 kpt 软件包
在本部分中,您将使用 kpt 下载一组配置,对其进行自定义,并将其应用到您在上一部分中创建的集群。
kpt
应安装在 Cloud Shell 环境中。如果不是,请使用以下命令进行安装:
在 Cloud Shell 中,安装 kpt:
sudo apt update && sudo apt-get install google-cloud-sdk-kpt
下载一组示例配置。如需了解详情,请参阅
kpt pkg get
。kpt pkg get https://github.com/GoogleContainerTools/kpt.git/package-examples/wordpress@v0.9
上述命令会下载 kpt GitHub 代码库中提供的
wordpress
示例软件包,其版本标记为v0.9
。检查软件包内容:
kpt pkg tree
。kpt pkg tree wordpress
输出如下所示:
Package "wordpress" ├── [Kptfile] Kptfile wordpress ├── [service.yaml] Service wordpress ├── deployment │ ├── [deployment.yaml] Deployment wordpress │ └── [volume.yaml] PersistentVolumeClaim wp-pv-claim └── Package "mysql" ├── [Kptfile] Kptfile mysql ├── [deployment.yaml] PersistentVolumeClaim mysql-pv-claim ├── [deployment.yaml] Deployment wordpress-mysql └── [deployment.yaml] Service wordpress-mysql
该软件包包含两个软件包,分别为顶层的
wordpress
和子软件包wordpress/mysql
,这两个软件包都包含元数据文件Kptfile
。Kptfile
仅由 kpt 本身使用,包含有关软件包的上游源代码、自定义和验证的数据。更新软件包的标签
软件包作者添加了一个渲染流水线,通常用于传达预期的自定义内容。
less wordpress/Kptfile
内容应如下所示:
apiVersion: kpt.dev/v1 kind: Kptfile metadata: name: wordpress upstream: type: git git: repo: https://github.com/GoogleContainerTools/kpt directory: /package-examples/wordpress ref: v0.9 updateStrategy: resource-merge upstreamLock: type: git git: repo: https://github.com/GoogleContainerTools/kpt directory: /package-examples/wordpress ref: package-examples/wordpress/v0.9 commit: b9ea0bca019dafa9f9f91fd428385597c708518c info: emails: - kpt-team@google.com description: This is an example wordpress package with mysql subpackage. pipeline: mutators: - image: gcr.io/kpt-fn/set-labels:v0.1 configMap: app: wordpress validators: - image: gcr.io/kpt-fn/kubeval:v0.3
您可以使用自己喜欢的编辑器将 set-label 函数的参数从
app: wordpress
更改为app: my-wordpress
使用您偏爱的代码编辑器修改 MySQL 部署
wordpress/mysql/deployment.yaml
,以更改 MySQL 版本。此外,如需进一步增强安全性,请将MYSQL_ROOT_PASSWORD
变量更改为MYSQL_PASSWORD
,并添加以下变量:MYSQL_USER
MYSQL_RANDOM_ROOT_PASSWORD
MYSQL_DATABASE
之前:
[...] containers: - name: mysql image: mysql:5.6 ports: - name: mysql protocol: TCP containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password [...]
之后:
[...] containers: - name: mysql image: mysql:8.0 ports: - name: mysql protocol: TCP containerPort: 3306 env: - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password - name: MYSQL_RANDOM_ROOT_PASSWORD value: '1' - name: MYSQL_USER value: wordpress - name: MYSQL_DATABASE value: wordpress [...]
使用您偏爱的代码编辑器修改 Wordpress 部署
wordpress/deployment/deployment.yaml
,以更改 Wordpress 版本并添加WORDPRESS_DB_USER
变量。之前:
[...] containers: - name: wordpress image: wordpress:6.1-apache ports: - name: wordpress protocol: TCP containerPort: 80 env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password [...]
之后:
[...] containers: - name: wordpress image: wordpress:4.8-apache ports: - name: wordpress protocol: TCP containerPort: 80 env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password - name: WORDPRESS_DB_USER value: wordpress [...]
与仅通过参数运行的工具不同,kpt 允许您使用编辑器直接修改文件,然后仍合并上游更新。您可以直接修改
deployment.yaml
,而无需编写补丁程序或在流水线中创建函数。使用
sample-annotation: sample-value
为配置添加注解。kpt fn eval wordpress --image gcr.io/kpt-fn/set-annotations:v0.1 \ -- sample-annotation=sample-value
输出应类似如下:
[RUNNING] "gcr.io/kpt-fn/set-annotations:v0.1" [PASS] "gcr.io/kpt-fn/set-annotations:v0.1"
如需查看新注解,您可以检查任何配置值,一个简单的例子是
wordpress/service.yaml
在此示例中,我们以软件包作者未曾计划的方式使用函数进行了自定义。kpt 能够支持声明式和命令式函数执行,从而适用于广泛的场景。
如果此软件包是使用基础架构即代码开发的,我们需要转到软件包的来源并在该处修改代码。
运行流水线,并通过 kpt 使用 kubeval 验证更改。
kpt fn render wordpress
软件包作者在流水线中包含了验证步骤:
... validators: - image: gcr.io/kpt-fn/kubeval:v0.3
此渲染流水线的成功输出如下所示:
Package "wordpress/mysql": [RUNNING] "gcr.io/kpt-fn/set-labels:v0.1" [PASS] "gcr.io/kpt-fn/set-labels:v0.1" in 1.3s Package "wordpress": [RUNNING] "gcr.io/kpt-fn/set-labels:v0.1" [PASS] "gcr.io/kpt-fn/set-labels:v0.1" in 1.3s [RUNNING] "gcr.io/kpt-fn/kubeval:v0.3" [PASS] "gcr.io/kpt-fn/kubeval:v0.3" in 3.7s Successfully executed 3 function(s) in 2 package(s).
此步骤是使用 Kubernetes 资源模型的好处的一个示例:由于您的配置在此知名模型中表示,您可以使用现有的 Kubernetes 工具(例如 kubeval)。
检查本地配置版本和上游配置之间的区别:
kpt pkg diff wordpress
初始化软件包以进行部署:
kpt live init wordpress
上述命令用于构建软件包中的配置清单。此外,当您从软件包中移除配置时,kpt 会使用清单来删减配置。如需了解详情,请参阅
kpt live
。创建包含 MySQL 密码的 Secret:
kubectl create secret generic mysql-pass --from-literal=password=foobar
将配置应用到您的 GKE 集群。
kpt live apply wordpress
输出如下所示:
installing inventory ResourceGroup CRD. inventory update started inventory update finished apply phase started service/wordpress apply successful service/wordpress-mysql apply successful deployment.apps/wordpress apply successful deployment.apps/wordpress-mysql apply successful persistentvolumeclaim/mysql-pv-claim apply successful persistentvolumeclaim/wp-pv-claim apply successful apply phase finished reconcile phase started service/wordpress reconcile successful service/wordpress-mysql reconcile successful deployment.apps/wordpress reconcile pending deployment.apps/wordpress-mysql reconcile pending persistentvolumeclaim/mysql-pv-claim reconcile pending persistentvolumeclaim/wp-pv-claim reconcile pending persistentvolumeclaim/wp-pv-claim reconcile successful persistentvolumeclaim/mysql-pv-claim reconcile successful deployment.apps/wordpress-mysql reconcile successful deployment.apps/wordpress reconcile successful reconcile phase finished inventory update started inventory update finished apply result: 6 attempted, 6 successful, 0 skipped, 0 failed reconcile result: 6 attempted, 6 successful, 0 skipped, 0 failed, 0 timed out
等待几分钟,然后验证一切是否按预期运行:
kpt live status wordpress
输出如下所示:
inventory-88521939/deployment.apps/default/wordpress is Current: Deployment is available. Replicas: 1 inventory-88521939/persistentvolumeclaim/default/wp-pv-claim is Current: PVC is Bound inventory-88521939/service/default/wordpress-mysql is Current: Service is ready inventory-88521939/persistentvolumeclaim/default/mysql-pv-claim is Current: PVC is Bound inventory-88521939/deployment.apps/default/wordpress-mysql is Current: Deployment is available. Replicas: 1 inventory-88521939/service/default/wordpress is Current: Service is ready
更新本地软件包
在本节中,您将使用上游软件包的一些更改来更新软件包的本地版本。
为您的配置创建 Git 代码库,并配置您的电子邮件地址和名称。您需要一个本地 Git 代码库才能更新软件包。请将
YOUR_EMAIL
替换为您的电子邮件地址,将YOUR_NAME
替换为您的名称。cd wordpress/ git init -b main git config user.email "YOUR_EMAIL" git config user.name "YOUR_NAME"
提交配置:
git add . git commit -m "First version of Wordpress package" cd ..
更新本地软件包。在此步骤中,您将从上游拉取
v0.10
版本。kpt pkg update wordpress@v0.10
查看上游的更新会应用到您的本地软件包:
cd wordpress/ git diff
在此示例中,更新已将 Wordpress 部署卷从 3Gi 更改为 4Gi。您也可以查看自己的更改。
提交所做的更改:
git commit -am "Update to package version v0.10"
应用新版本的软件包:
kpt live apply .
移除资源和软件包
由于 kpt 会跟踪它创建的资源,因此当您从软件包中删除资源时,kpt 可能会从集群中删减资源。它也可以从集群中完全移除软件包。在本部分中,您将从软件包中移除资源,然后移除软件包。
从软件包中移除
service.yaml
文件:git rm service.yaml git commit -m "Remove service"
应用更改,然后验证 kpt 是否删减了 wordpress 服务:
kpt live apply . kubectl get svc
从集群中移除软件包的其余内容,然后验证集群中是否没有剩余内容:
kpt live destroy . kubectl get deployment
使用 kpt 强化 GKE
kpt live
命令不是将软件包应用于 Kubernetes 集群的唯一方法。在本部分中,您将在基本但实际的场景中将 kpt 与 Config Sync 结合使用。借助 Config Sync 工具,您可以通过 Git 代码库集中、统一、以声明方式管理所有 Kubernetes 集群的配置。您在本教程中使用的 GKE Enterprise 包含 Config Sync。
GKE Enterprise 安全蓝图为基于 GKE Enterprise 的工作负载提供了一系列预封装的安全设置。在本部分中,您将使用限制流量蓝图(以及它在 GitHub 代码库中的目录)。您使用 kpt 下载 default-deny
软件包。该软件包默认使用 Kubernetes 网络政策来拒绝 GKE 集群中的任何流量(DNS 解析除外)。为了应用配置,您随即将配置提交到 Config Sync Git 代码库。
安装 Config Sync
在本部分中,您将创建 Config Sync 需要的 Git 代码库,然后在 GKE 集群上安装 Config Sync。
在 Cloud Shell 中,使用 Cloud Source Repositories 为 Config Sync 创建 Git 代码库:
cd ~ gcloud source repos create config-management
生成 SSH 密钥对,以向 Git 代码库进行身份验证:
cd ~ ssh-keygen -t rsa -b 4096 -N '' \ -f cloud_source_repositories_key
创建包含 SSH 私钥的 Kubernetes Secret 以访问 Git 代码库:
kubectl create ns config-management-system && \ kubectl create secret generic git-creds \ --namespace=config-management-system \ --from-file=ssh=cloud_source_repositories_key
显示公钥,然后复制它:
cat cloud_source_repositories_key.pub
转到 Cloud Source Repositories
管理 SSH 密钥页面。
在随后显示的注册 SSH 密钥对话框中,输入以下值:
- 在密钥名称字段中,输入
config-management
。 - 在密钥字段中,粘贴公钥。
- 点击注册。
- 在密钥名称字段中,输入
将 Git 代码库克隆到 Cloud Shell:
gcloud source repos clone config-management cd config-management git checkout -b main
下载名为
nomos
的 Config Sync 命令行工具。nomos
应安装在 Cloud Shell 环境中。如果不是,请使用以下命令进行安装:sudo apt update && sudo apt-get install google-cloud-sdk-nomos
初始化 Config Sync 代码库:
nomos init git add . git commit -m "Config Management directory structure" git push -u origin main
部署 Config Sync Operator:
gsutil cp gs://config-management-release/released/latest/config-management-operator.yaml /tmp/config-management-operator.yaml kubectl apply -f /tmp/config-management-operator.yaml
配置 Config Sync
创建 ConfigManagement 自定义资源以配置 Config Sync:
PROJECT=$(gcloud config get-value project) EMAIL=$(gcloud config get-value account) cat <<EOF > /tmp/config-management.yaml apiVersion: configmanagement.gke.io/v1 kind: ConfigManagement metadata: name: config-management spec: clusterName: kpt-tutorial git: syncRepo: ssh://${EMAIL}@source.developers.google.com:2022/p/${PROJECT}/r/config-management syncBranch: main secretType: ssh EOF kubectl -n config-management-system \ apply -f /tmp/config-management.yaml
如需了解更多安装选项,请参阅安装 Config Sync 文档。
在 Cloud Shell 中,验证 Config Sync 是否正常运行:
nomos status --contexts=$(kubectl config current-context)
此命令会返回
SYNCED
状态。Config Sync 初始化可能需要一些时间。如果状态未更新,请等待几分钟,然后重新运行该命令。
应用 GKE Enterprise 安全蓝图
在本部分中,您将使用 kpt 下载限制流量 GKE Enterprise 安全蓝图的 default-deny
软件包。然后,使用 Config Sync 仅将软件包应用于 default
命名空间。
下载
default-deny
软件包:cd ~ kpt pkg get https://github.com/GoogleCloudPlatform/anthos-security-blueprints.git/restricting-traffic/default-deny ./
您可以浏览软件包的内容:
default-deny/Kptfile
文件包含软件包的元数据,而default-deny/default-deny.yaml
文件包含 Kubernetes NetworkPolicy,它是此蓝图的仅有配置。使用 kpt 复制 Config Sync 代码库中软件包的内容,然后添加标签以进行自定义:
kpt fn source default-deny/ | \ kpt fn eval - --image=gcr.io/kpt-fn/set-annotations:v0.1 -- \ anthos-security-blueprint=restricting-traffic | \ kpt fn sink ~/config-management/namespaces/default/
如本示例中所示,您可以使用管道将
kpt fn
命令连在一起。通过将kpt fn
命令连在一起,您可以读取配置、根据需要修改配置并写入结果。您可以根据需要将任意数量的kpt fn
命令连在一起。在 Config Sync 代码库中创建
namespace.yaml
文件:cat >> ~/config-management/namespaces/default/namespace.yaml <<EOF apiVersion: v1 kind: Namespace metadata: name: default EOF
default
命名空间存在于 GKE 集群中,但 Config Sync 不管理该命名空间。在此步骤中创建目录和文件时,请让 Config Sync 管理该命名空间。如需将该软件包同时应用于多个命名空间,您可以创建抽象命名空间。验证 Kubernetes NetworkPolicy 是否已写入 Config Sync 代码库,以及是否使用
anthos-security-blueprint: restricting-traffic
进行注解:cat config-management/namespaces/default/default-deny.yaml
输出如下所示:
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: # kpt-merge: /default-deny name: default-deny annotations: internal.kpt.dev/upstream-identifier: 'networking.k8s.io|NetworkPolicy|default|default-deny' anthos-security-blueprint: restricting-traffic spec: policyTypes: - Ingress - Egress podSelector: {} egress: - to: - namespaceSelector: matchLabels: k8s-namespace: kube-system podSelector: matchExpressions: - key: k8s-app operator: In values: ["kube-dns", "node-local-dns"] ports: - protocol: TCP port: 53 - protocol: UDP port: 53
提交并推送更改:
cd ~/config-management/ git add namespaces/default/ git commit -m "Default deny" git push
验证新政策是否已应用:
kubectl get networkpolicies
如果新政策不存在,请等待几秒钟,然后再次运行该命令。默认情况下,Config Sync 每 15 秒更新一次配置。如果您需要进行一些额外的问题排查,请运行以下命令以获得任何潜在的 Config Sync 错误的相关信息:
nomos status --contexts=$(kubectl config current-context)
如需测试新政策,请在
default
命名空间中运行的 pod 中获取一个 shell:kubectl -n default run -i --tty --rm test \ --image=busybox --restart=Never -- sh
尝试 ping
8.8.8.8
,然后查看它是否未按预期运行:ping -c 3 -W 1 8.8.8.8
输出如下所示:
PING 8.8.8.8 (8.8.8.8): 56 data bytes --- 8.8.8.8 ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss
尝试查询 Kubernetes API 服务器,然后查看它是否未按预期运行:
wget --timeout=3 https://${KUBERNETES_SERVICE_HOST}
输出如下所示:
Connecting to 10.3.240.1 (10.3.240.1:443) wget: download timed out
退出 pod:
exit
清除数据
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
- 在 Google Cloud 控制台中,进入管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
删除资源
如果您希望保留在本教程中使用的 Google Cloud 项目,则可以删除 Git 代码库和 GKE 集群。在 Cloud Shell 中,运行以下脚本:
gcloud source repos delete config-management --quiet
gcloud container clusters delete kpt-tutorial \
--async --quiet --zone=us-central1-a
后续步骤
- 详细了解 Config Sync 及其组件。
- 了解用于验证应用部署配置的 Policy Controller。
- 探索有关 Google Cloud 的参考架构、图表和最佳实践。查看我们的 Cloud Architecture Center。