当前位置: 首页 > 工具软件 > Krane > 使用案例 >

AlmaLinux 9 安装和体验 krane

别烨熠
2023-12-01

什么是 krane

krane是一个命令行工具,它可以帮助你向Kubernetes命名空间发送更改并了解结果。
为什么不直接使用标准的kubectl apply进行部署?Krane在引擎盖下使用了它。然而,kubectl apply却给用户留下了一些棘手的问题。刚刚发生了什么?它成功了吗?
特别是在CI/CD环境中,我们需要对每次部署有一个明确的、可操作的成功/失败的结果。提供这一点是krane的基本目标,它已经发展到支持以下核心功能。
 观察你要求的变化,确保它们成功推出。
⁉️ 为失败的修改提供调试信息。
预先部署某些类型的资源(例如 ConfigMap、PersistentVolumeClaim),以确保在部署可能消费它们的资源(例如 Deployment)时,最新版本可用。
 从加密的EJSON中创建Kubernetes秘密,你可以安全地提交到你的存储库。
 在部署开始时使用bare pods运行任务(使用案例:Rails迁移)。
如果你需要在部署前渲染模板中的动态值,你可以使用krane render。与此同时,这个 repo 还包括运行任务和重启部署的工具。

Github 代码库

https://github.com/Shopify/krane

安装 krane

先安装ruby,ruby-devel,gcc-c++,

sudo dnf install -y ruby ruby-devel gcc-c++

然后安装krane,

sudo gem install krane

使用 krane

准备

请将CONTEXT修改为你使用的kubernetes context,

kubectl create namespace demo

NAMESPACE=demo
CONTEXT=k8s-admin@local

示例1

发布一个 deployment,

cat << EOF | krane deploy $NAMESPACE $CONTEXT -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
EOF

示例1输出日志,

[INFO][2023-01-30 10:48:03 +0800]
[INFO][2023-01-30 10:48:03 +0800]       ------------------------------------Phase 1: Initializing deploy------------------------------------
[INFO][2023-01-30 10:48:03 +0800]       All required parameters and files are present
[INFO][2023-01-30 10:48:03 +0800]       Discovering resources:
[INFO][2023-01-30 10:48:03 +0800]         - Deployment/nginx-deployment
[INFO][2023-01-30 10:48:07 +0800]
[INFO][2023-01-30 10:48:07 +0800]       ----------------------------Phase 2: Checking initial resource statuses-----------------------------
[INFO][2023-01-30 10:48:07 +0800]       Deployment/nginx-deployment                       Not Found
[INFO][2023-01-30 10:48:07 +0800]
[INFO][2023-01-30 10:48:07 +0800]       ----------------------------------Phase 3: Deploying all resources----------------------------------
[INFO][2023-01-30 10:48:07 +0800]       Deploying Deployment/nginx-deployment (timeout: 420s)
[INFO][2023-01-30 10:48:11 +0800]       Successfully deployed in 3.6s: Deployment/nginx-deployment
[INFO][2023-01-30 10:48:11 +0800]
[INFO][2023-01-30 10:48:11 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 10:48:11 +0800]       Successfully deployed 1 resource
[INFO][2023-01-30 10:48:11 +0800]
[INFO][2023-01-30 10:48:11 +0800]       Successful resources
[INFO][2023-01-30 10:48:11 +0800]       Deployment/nginx-deployment                       3 replicas, 3 updatedReplicas, 3 availableReplicas

示例2

发布一个 non-namespaced 资源,

cat << EOF | krane global-deploy $CONTEXT -f - --selector app=krane
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: testing-storage-class
  labels:
    app: krane
provisioner: kubernetes.io/no-provisioner
EOF

示例2输出日志,

[INFO][2023-01-30 10:54:38 +0800]
[INFO][2023-01-30 10:54:38 +0800]       ------------------------------------Phase 1: Initializing deploy------------------------------------
[INFO][2023-01-30 10:54:38 +0800]       Using resource selector app=krane
[INFO][2023-01-30 10:54:38 +0800]       All required parameters and files are present
[INFO][2023-01-30 10:54:38 +0800]       Discovering resources:
[INFO][2023-01-30 10:54:39 +0800]         - StorageClass/testing-storage-class
[INFO][2023-01-30 10:54:39 +0800]
[INFO][2023-01-30 10:54:39 +0800]       ----------------------------Phase 2: Checking initial resource statuses-----------------------------
[INFO][2023-01-30 10:54:39 +0800]       StorageClass/testing-storage-class                Not Found
[INFO][2023-01-30 10:54:39 +0800]
[INFO][2023-01-30 10:54:39 +0800]       ----------------------------------Phase 3: Deploying all resources----------------------------------
[INFO][2023-01-30 10:54:39 +0800]       Deploying StorageClass/testing-storage-class (timeout: 300s)
[WARN][2023-01-30 10:54:41 +0800]       Don't know how to monitor resources of type StorageClass. Assuming StorageClass/testing-storage-class deployed successfully.
[INFO][2023-01-30 10:54:41 +0800]       Successfully deployed in 1.6s: StorageClass/testing-storage-class
[INFO][2023-01-30 10:54:41 +0800]
[INFO][2023-01-30 10:54:41 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 10:54:41 +0800]       Successfully deployed 1 resource
[INFO][2023-01-30 10:54:41 +0800]
[INFO][2023-01-30 10:54:41 +0800]       Successful resources
[INFO][2023-01-30 10:54:41 +0800]       StorageClass/testing-storage-class                Exists

示例3

重启1个 deployment,

krane restart $NAMESPACE $CONTEXT --deployments=nginx-deployment

示例3输入日志,

[INFO][2023-01-30 10:57:15 +0800]
[INFO][2023-01-30 10:57:15 +0800]       -----------------------------------Phase 1: Initializing restart------------------------------------
[INFO][2023-01-30 10:57:15 +0800]       Configured to restart deployments by name: nginx-deployment
[INFO][2023-01-30 10:57:15 +0800]
[INFO][2023-01-30 10:57:15 +0800]       ------------------------------------Phase 2: Triggering restart-------------------------------------
[INFO][2023-01-30 10:57:15 +0800]       Triggered `Deployment/nginx-deployment` restart
[INFO][2023-01-30 10:57:15 +0800]
[INFO][2023-01-30 10:57:15 +0800]       ------------------------------------Phase 3: Waiting for rollout------------------------------------
[INFO][2023-01-30 10:57:19 +0800]       Successfully restarted in 3.0s: Deployment/nginx-deployment
[INFO][2023-01-30 10:57:19 +0800]
[INFO][2023-01-30 10:57:19 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 10:57:19 +0800]       Successfully restarted 1 resource
[INFO][2023-01-30 10:57:19 +0800]
[INFO][2023-01-30 10:57:19 +0800]       Successful resources
[INFO][2023-01-30 10:57:19 +0800]       Deployment/nginx-deployment                       3 replicas, 3 updatedReplicas, 3 availableReplicas

示例4

krane run是一个用于触发一次性工作的工具,
先部署一个PodTemplate,

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-configmap-data
  labels:
    name: demo-configmap-data
    app: demo
data:
  datapoint1: value1
  datapoint2: value2
---
apiVersion: v1
kind: PodTemplate
metadata:
  name: demo-pod-template-runner
  labels:
    name: demo-pod-template-runner
    app: demo
template:
  metadata:
    name: task-runner
    labels:
      name: runner
      app: demo
  spec:
    restartPolicy: Never
    containers:
    - name: task-runner
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["sh", "-c", "echo 'Hello from the command runner!' && test 1 -eq 1"]
      env:
      - name: CONFIG
        valueFrom:
          configMapKeyRef:
            name: demo-configmap-data
            key: datapoint1
EOF

输出日志,

[INFO][2023-01-30 11:04:00 +0800]
[INFO][2023-01-30 11:04:00 +0800]       ------------------------------------Phase 1: Initializing deploy------------------------------------
[INFO][2023-01-30 11:04:00 +0800]       All required parameters and files are present
[INFO][2023-01-30 11:04:00 +0800]       Discovering resources:
[INFO][2023-01-30 11:04:01 +0800]         - ConfigMap/demo-configmap-data
[INFO][2023-01-30 11:04:01 +0800]         - PodTemplate/demo-pod-template-runner
[INFO][2023-01-30 11:04:05 +0800]
[INFO][2023-01-30 11:04:05 +0800]       ----------------------------Phase 2: Checking initial resource statuses-----------------------------
[INFO][2023-01-30 11:04:05 +0800]       ConfigMap/demo-configmap-data                     Available
[INFO][2023-01-30 11:04:05 +0800]       PodTemplate/demo-pod-template-runner              Not Found
[INFO][2023-01-30 11:04:05 +0800]
[INFO][2023-01-30 11:04:05 +0800]       ------------------------------Phase 3: Predeploying priority resources------------------------------
[INFO][2023-01-30 11:04:05 +0800]       Deploying ConfigMap/demo-configmap-data (timeout: 30s)
[INFO][2023-01-30 11:04:05 +0800]       Successfully deployed in 0.1s: ConfigMap/demo-configmap-data
[INFO][2023-01-30 11:04:05 +0800]
[INFO][2023-01-30 11:04:05 +0800]
[INFO][2023-01-30 11:04:05 +0800]       ----------------------------------Phase 4: Deploying all resources----------------------------------
[INFO][2023-01-30 11:04:05 +0800]       Deploying resources:
[INFO][2023-01-30 11:04:05 +0800]       - ConfigMap/demo-configmap-data (timeout: 30s)
[INFO][2023-01-30 11:04:05 +0800]       - PodTemplate/demo-pod-template-runner (timeout: 300s)
[INFO][2023-01-30 11:04:08 +0800]       The following resources were pruned: podtemplate/pod-template-runner
[INFO][2023-01-30 11:04:09 +0800]       Successfully deployed in 3.8s: ConfigMap/demo-configmap-data, PodTemplate/demo-pod-template-runner
[INFO][2023-01-30 11:04:09 +0800]
[INFO][2023-01-30 11:04:09 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 11:04:09 +0800]       Pruned 1 resource and successfully deployed 2 resources
[INFO][2023-01-30 11:04:09 +0800]
[INFO][2023-01-30 11:04:09 +0800]       Successful resources
[INFO][2023-01-30 11:04:09 +0800]       ConfigMap/demo-configmap-data                     Available
[INFO][2023-01-30 11:04:09 +0800]       PodTemplate/demo-pod-template-runner              Available

执行krane run

krane run $NAMESPACE $CONTEXT --arguments="hello world!" --command="echo" --template=demo-pod-template-runner

输出日志,

[INFO][2023-01-30 11:05:15 +0800]
[INFO][2023-01-30 11:05:15 +0800]       -------------------------------------Phase 1: Initializing task-------------------------------------
[INFO][2023-01-30 11:05:15 +0800]       Validating configuration
[INFO][2023-01-30 11:05:15 +0800]       Using namespace 'demo' in context 'k8s-admin@local'
[INFO][2023-01-30 11:05:15 +0800]       Using template 'demo-pod-template-runner'
[INFO][2023-01-30 11:05:15 +0800]
[INFO][2023-01-30 11:05:15 +0800]       ----------------------------------------Phase 2: Running pod----------------------------------------
[INFO][2023-01-30 11:05:15 +0800]       Creating pod 'task-runner-6f8ddd03da6dd27e'
[INFO][2023-01-30 11:05:15 +0800]       Pod creation succeeded
[INFO][2023-01-30 11:05:15 +0800]
[INFO][2023-01-30 11:05:15 +0800]       --------------------------------------Phase 3: Streaming logs---------------------------------------
[INFO][2023-01-30 11:05:15 +0800]       Streaming logs from Pod/task-runner-6f8ddd03da6dd27e container 'task-runner':

[INFO][2023-01-30 11:05:26 +0800]       hello world!

[INFO][2023-01-30 11:05:28 +0800]       Successfully ran in 13.1s: Pod/task-runner-6f8ddd03da6dd27e
[INFO][2023-01-30 11:05:28 +0800]
[INFO][2023-01-30 11:05:28 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 11:05:28 +0800]       Successfully ran 1 resource
[INFO][2023-01-30 11:05:28 +0800]
[INFO][2023-01-30 11:05:28 +0800]       Successful resources
[INFO][2023-01-30 11:05:28 +0800]       Pod/task-runner-6f8ddd03da6dd27e                  Succeeded

示例5

krane render是一个将ERB模板渲染成原始Kubernetes YAML的工具。它对输出YAML很有用,可以传递给其他工具,用于验证或自省。
自省(introspection)是机器人API、能力、监控及被监控功能操作的基础。

cat << EOF | krane render --bindings=current_sha=Changeme -f - > web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  annotations:
    shipit.shopify.io/restart: "true"
  labels:
    name: web-deployment

spec:
  replicas: 1
  selector:
    matchLabels:
      name: web-deployment
  progressDeadlineSeconds: 60
  template:
    metadata:
      labels:
        name: web-deployment
    spec:
      containers:
      - name: web
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["tail", "-f", "/dev/null"]
        ports:
        - containerPort: 80
          name: http
        env:
        - name: GITHUB_REV
          value: "<%= current_sha %>"
      - name: sidecar
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["tail", "-f", "/dev/null"]
EOF

输出日志,

[INFO][2023-01-30 11:40:48 +0800]
[INFO][2023-01-30 11:40:48 +0800]       ---------------------------------Phase 1: Initializing render task----------------------------------
[INFO][2023-01-30 11:40:48 +0800]       Validating configuration
[INFO][2023-01-30 11:40:48 +0800]
[INFO][2023-01-30 11:40:48 +0800]       -----------------------------------Phase 2: Rendering template(s)-----------------------------------
[INFO][2023-01-30 11:40:48 +0800]       Rendering from_stdin.yml.erb...
[INFO][2023-01-30 11:40:48 +0800]       Rendered from_stdin.yml.erb
[INFO][2023-01-30 11:40:48 +0800]
[INFO][2023-01-30 11:40:48 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 11:40:48 +0800]       Successfully rendered 1 template(s)
[INFO][2023-01-30 11:40:48 +0800]

查看生成的web-deployment.yaml

cat web-deployment.yaml

输出结果,

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  annotations:
    shipit.shopify.io/restart: "true"
  labels:
    name: web-deployment

spec:
  replicas: 1
  selector:
    matchLabels:
      name: web-deployment
  progressDeadlineSeconds: 60
  template:
    metadata:
      labels:
        name: web-deployment
    spec:
      containers:
      - name: web
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["tail", "-f", "/dev/null"]
        ports:
        - containerPort: 80
          name: http
        env:
        - name: GITHUB_REV
          value: "Changeme"
      - name: sidecar
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["tail", "-f", "/dev/null"]

示例5

由于Kubernetes的Secret只有base64编码,因此Kubernetes的Secret不应该被提交到你的仓库。相反,krane支持从模板目录中的加密ejson文件中生成Secret。下面示例展示如何使用这一功能。
先安装ejson,

sudo gem install ejson

生成一个新的密钥对,

ejson keygen

输出结果,

Public Key:
0337c353428b0366c38423290daa1dab74abf2aebb0c0f16b97499b4dc579802
Private Key:
97bf189c7d64bfb010e7b7f5c2a5d961b03834529ff888c83198a6e647b6ebf9

配置为环境变量,

YOUR_PUBLIC_KEY=0337c353428b0366c38423290daa1dab74abf2aebb0c0f16b97499b4dc579802
YOUR_PRIVATE_KEY=97bf189c7d64bfb010e7b7f5c2a5d961b03834529ff888c83198a6e647b6ebf9

用新的密钥对在你的目标命名空间创建一个Kubernetes秘密,

kubectl create secret generic ejson-keys --from-literal=$YOUR_PUBLIC_KEY=$YOUR_PRIVATE_KEY --namespace=$NAMESPACE

警告:不要使用 apply 来创建 ejson-keys Secret,如果 ejson-keys 是可修改的,则 krane 会失败。这一保障措施是为了防止你的私钥被意外删除。

(可选但强烈建议)将密钥对备份到安全的地方,如密码管理器,以备灾难恢复之用。
在你的模板目录中(与你的Kubernetes模板一起),创建secrets.ejson,其格式如下所示。对于TLS Secret,_type Secret的值应该是 kubernetes.io/tls,对于所有其他的Secret则是 Opaque。数据键必须是一个json对象,但其键和值可以是你需要的任何东西。

cat << EOF > secrets.ejson
{
  "_public_key": "$YOUR_PUBLIC_KEY",
  "kubernetes_secrets": {
    "catphotoscom": {
      "_type": "kubernetes.io/tls",
      "data": {
        "tls.crt": "cert-data-here",
        "tls.key": "key-data-here"
      }
    },
    "monitoring-token": {
      "_type": "Opaque",
      "data": {
        "api-token": "token-value-here"
      }
    }
  }
}
EOF

加密文件,

ejson encrypt secrets.ejson

提交加密后的文件并进行部署。部署将从 kubernetes_secrets 密钥中的数据创建Secret。ejson文件必须包含在传递给–filenames的资源中,它不能通过stdin读取。

krane deploy $NAMESPACE $CONTEXT -f secrets.ejson

输出日志,

[INFO][2023-01-30 12:05:24 +0800]
[INFO][2023-01-30 12:05:24 +0800]       ------------------------------------Phase 1: Initializing deploy------------------------------------
[INFO][2023-01-30 12:05:24 +0800]       All required parameters and files are present
[INFO][2023-01-30 12:05:24 +0800]       Discovering resources:
[INFO][2023-01-30 12:05:25 +0800]         - Secret/catphotoscom (from ejson)
[INFO][2023-01-30 12:05:25 +0800]         - Secret/monitoring-token (from ejson)
[INFO][2023-01-30 12:05:29 +0800]
[INFO][2023-01-30 12:05:29 +0800]       ----------------------------Phase 2: Checking initial resource statuses-----------------------------
[INFO][2023-01-30 12:05:29 +0800]       Secret/catphotoscom                               Not Found
[INFO][2023-01-30 12:05:29 +0800]       Secret/monitoring-token                           Not Found
[INFO][2023-01-30 12:05:29 +0800]
[INFO][2023-01-30 12:05:29 +0800]       ------------------------------Phase 3: Predeploying priority resources------------------------------
[INFO][2023-01-30 12:05:29 +0800]       Deploying resources:
[INFO][2023-01-30 12:05:29 +0800]       - Secret/catphotoscom (timeout: 30s)
[INFO][2023-01-30 12:05:29 +0800]       - Secret/monitoring-token (timeout: 30s)
[INFO][2023-01-30 12:05:29 +0800]       Successfully deployed in 0.2s: Secret/catphotoscom, Secret/monitoring-token
[INFO][2023-01-30 12:05:29 +0800]
[INFO][2023-01-30 12:05:29 +0800]
[INFO][2023-01-30 12:05:29 +0800]       ----------------------------------Phase 4: Deploying all resources----------------------------------
[INFO][2023-01-30 12:05:29 +0800]       Deploying resources:
[INFO][2023-01-30 12:05:29 +0800]       - Secret/catphotoscom (timeout: 30s)
[INFO][2023-01-30 12:05:29 +0800]       - Secret/monitoring-token (timeout: 30s)
[INFO][2023-01-30 12:05:33 +0800]       The following resources were pruned: configmap/demo-configmap-data, podtemplate/demo-pod-template-runner
[INFO][2023-01-30 12:05:33 +0800]       Successfully deployed in 4.0s: Secret/catphotoscom, Secret/monitoring-token
[INFO][2023-01-30 12:05:33 +0800]
[INFO][2023-01-30 12:05:33 +0800]       ------------------------------------------Result: SUCCESS-------------------------------------------
[INFO][2023-01-30 12:05:33 +0800]       Pruned 2 resources and successfully deployed 2 resources
[INFO][2023-01-30 12:05:33 +0800]
[INFO][2023-01-30 12:05:33 +0800]       Successful resources
[INFO][2023-01-30 12:05:33 +0800]       Secret/catphotoscom                               Available
[INFO][2023-01-30 12:05:33 +0800]       Secret/monitoring-token                           Available

注意:由于ejson密钥中的前导下划线用于跳过相关值的加密,krane在为Kubernetes Secret数据创建密钥时将剥离这些前导下划线。例如,鉴于下面的ejson数据,monitoring-token的Secret将有键api-tokenpropety(不是_property)。

{
 "_public_key": "YOUR_PUBLIC_KEY",
 "kubernetes_secrets": {
   "monitoring-token": {
     "_type": "kubernetes.io/tls",
     "data": {
       "api-token": "EJ[ENCRYPTED]",
       "_property": "some unencrypted value"
     }
   }
 }

查看Secret,

kubectl describe secret catphotoscom -n $NAMESPACE

输出结果,

Name:         catphotoscom
Namespace:    demo
Labels:       name=catphotoscom
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.key:  13 bytes
tls.crt:  14 bytes
[oracle@almalinux9 krane]$ kubectl get secret catphotoscom -n $NAMESPACE -o yaml
apiVersion: v1
data:
  tls.crt: Y2VydC1kYXRhLWhlcmU=
  tls.key: a2V5LWRhdGEtaGVyZQ==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"tls.crt":"Y2VydC1kYXRhLWhlcmU=","tls.key":"a2V5LWRhdGEtaGVyZQ=="},"kind":"Secret","metadata":{"annotations":{},"labels":{"name":"catphotoscom"},"name":"catphotoscom","namespace":"demo"},"type":"kubernetes.io/tls"}
  creationTimestamp: "2023-01-30T04:05:29Z"
  labels:
    name: catphotoscom
  name: catphotoscom
  namespace: demo
  resourceVersion: "43777"
  uid: b727fcdf-edf2-4532-89bf-4ea3cf6716d9
type: kubernetes.io/tls

完结!

 类似资料: