OpenKruise简介
OpenKruise来源
它是由阿里巴巴集团的阿里云团队维护和开发的,并且在2018年将其贡献给了云原生计算基金会(CNCF),成为了CNCF的孵化项目。

OpenKruise是什么?
OpenKruise 是一个基于 Kubernetes 的扩展项目,旨在增强和扩展 Kubernetes 的原生能力,以更好地支持大规模应用的管理和运维。它通过提供一系列自定义控制器和自定义资源(CRD),帮助用户在 Kubernetes 集群中更加灵活、高效地管理容器化应用。

核心组件有什么?
1.CloneSet:
功能:
用于管理一组具有相同模板的 Pod。类似于 Kubernetes 的 Deployment,但提供了更多高级特性,如灰度发布、并行和顺序更新策略、最大不可用副本数等。
用途:
适用于需要复杂更新策略和高可用性的应用场景。

2.SidecarSet:
功能:
用于管理 Sidecar 容器。可以动态地将 Sidecar 容器注入到指定的 Pod 中,而不需要修改 Pod 的模板。
用途:
适用于需要在多个应用 Pod 中添加统一的辅助容器,如日志收集、监控代理等。

3.StatefulSet:
功能:
扩展了 Kubernetes 的 StatefulSet 功能。支持有状态应用的管理,提供了更灵活的更新和扩展策略。
用途:
适用于有状态应用,如数据库、缓存服务等。

4.Advanced DaemonSet:
功能:
提供了比原生 Kubernetes DaemonSet 更加灵活的功能,如灰度发布、并行和顺序更新策略等。
用途:
适用于需要在每个节点上运行一个副本的应用,如监控代理、日志收集代理等。

5.BroadcastJob:
功能:
类似于 Kubernetes 的 Job,但用于在集群中所有或部分节点上运行一次性任务。
用途:
适用于需要在每个节点上执行一次性任务的场景,如节点初始化、数据分发等。

6.ImagePullJob:
功能:
用于在集群的所有或部分节点上预拉取镜像,以减少 Pod 启动时的延迟。
用途:
适用于需要快速启动大量 Pod 的场景,如批量部署、大规模弹性扩容等。

有什么特性和优势?
高级发布策略:
支持蓝绿发布、金丝雀发布等高级发布策略,提供更灵活的应用更新方式。
高可用性和容错性:
通过高级的副本管理和更新策略,确保应用的高可用性和容错性。
易于集成:
与 Kubernetes 原生功能无缝集成,用户可以在现有 Kubernetes 集群上直接使用 OpenKruise 提供的功能。
社区支持:
由阿里巴巴开源,并得到社区广泛支持和贡献,持续更新和优化。

适用于什么场景?
互联网企业:
需要频繁更新和部署的在线服务,如电商网站、社交平台等。
金融行业:
高可用性和高安全性要求的金融应用,如银行系统、交易平台等。
大数据和 AI:
需要大规模计算和数据处理的应用,如数据分析、机器学习等。
企业 IT:
企业内部的各类业务系统和应用,如 CRM、ERP 系统等

什么是OpenKruise的原地升级
因为后面会使用,这里详细讲一下

OpenKruise 的原地升级(In-Place Update)是一种更新策略,允许在不销毁和重建 Pod 的情况下直接更新 Pod 内的容器镜像或资源配置。这种方法与传统的替换策略不同,可以显著减少更新过程中应用的中断时间和资源开销。

原地升级的关键特性
无需重建 Pod:
优势:
避免了 Pod 重建过程中的网络重连、存储重新挂载等操作,减少了因重建导致的潜在服务中断和性能抖动。
用途:
特别适用于那些对重建敏感的应用,如状态有管理复杂的有状态应用。

减少资源开销:
优势:
在更新过程中,不需要重新调度和启动新的 Pod,从而减少了对集群资源的占用。
用途:
适用于资源紧张的集群环境,可以有效节约计算和存储资源。

提升更新速度:
优势:
直接更新现有 Pod 的容器镜像或配置,省去了 Pod 创建和销毁的时间,显著提升了更新操作的效率。
用途:
适用于需要快速更新的场景,如紧急补丁、快速迭代开发等。

使用原地升级的组件
CloneSet:
原地升级功能:
通过配置 CloneSet 的 inPlaceUpdateStrategy,可以实现对应用的原地升级。
适用场景:
需要频繁更新且对更新速度和资源开销有较高要求的无状态应用。

Advanced StatefulSet:
原地升级功能:
扩展了原生 StatefulSet 的能力,支持对有状态应用进行原地升级。
适用场景:
需要高可用性和快速更新的有状态应用,如数据库、缓存服务等。

原地升级的工作原理
镜像更新:
操作:
修改 Pod 的容器镜像标签或 ID。
过程:
控制器监控到更新请求后,直接在原有 Pod 上更新容器镜像,触发容器重启但不销毁 Pod。

资源更新:
操作:
修改 Pod 的资源请求和限制(如 CPU 和内存)。
过程:
控制器监控到更新请求后,直接在原有 Pod 上更新资源配置,可能触发资源重调度但不销毁 Pod。

应用环境

虚拟机

Ip 主机名 cpu 内存 硬盘
192.168.10.11 master01 2cpu双核 4G 100G
192.168.10.12 worker01 2cpu双核 4G 100G
192.168.10.13 worker02 2cpu双核 4G 100G

版本 centos7.9
已部署k8s-1.27

一、OpenKruise部署

本案例使用helm方式安装部署

Helm用于实现kubernetes中相互关联的多个yaml文件的安装部署,相当于linux系统中的yum工具

1.安装helm客户端工具
wget https://get.helm.sh/helm-v3.13.2-linux-amd64.tar.gz
tar xf helm-v3.13.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/bin/
helm version
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm repo list

详情请看
链接: k8s学习–helm的详细解释及安装和常用命令

  1. 通过 helm 安装

    helm repo add openkruise https://openkruise.github.io/charts/
    helm repo update
    helm search repo openkruise
    
    k create ns kruise-system
    # 添加标签  
    kubectl label namespace kruise-system app.kubernetes.io/managed-by=Helm  
      
    # 添加注解  
    kubectl annotate namespace kruise-system meta.helm.sh/release-name=openkruise  
    kubectl annotate namespace kruise-system meta.helm.sh/release-namespace=kruise-system
    
    helm -n newland install redis -f my-values.yaml ./redis
    
    
    kruise-system
    
    
    featureGates: "ImagePullJobGate=true"
    
    
    helm -n kruise-system install openkruise -f values.yaml ./ 
    
    
    helm -n kruise-system install openkruise -f my-values.yaml ./  --set  manager.image.repository=192.168.0.140:881/openkruise/kruise-manager
    
    helm  install openkruise -f my-values.yaml ./ 
    
    
    helm -n kruise-system install openkruise -f my-values.yaml ./  
    
    --set  manager.image.repository=openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager
    
    
    openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager:v1.7.0-alpha1.1
    
    
    openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager:v1.7.0-alpha1.1
    
    $ helm install kruise https://... --set  manager.image.repository=openkruise-registry.cn-shanghai.cr.aliyuncs.com/openkruise/kruise-manager
    
    
    # Firstly add openkruise charts repository if you haven't do this.
    $ helm repo add openkruise https://openkruise.github.io/charts/
    
    # [Optional]
    $ helm repo update
    
    # Install the latest version.
    $ helm install kruise openkruise/kruise --version 1.6.3
    
    helm install kruise openkruise/kruise --version 1.6.3 --set  manager.image.repository=192.168.0.140:881/openkruise/kruise-manager
    
    [root@longxi-master201 ~]# cat /usr/lib/systemd/system/docker.service
    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network-online.target firewalld.service containerd.service
    Wants=network-online.target
    Requires=docker.socket containerd.service
    
    [Service]
    Type=notify
    
    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    ExecReload=/bin/kill -s HUP $MAINPID
    TimeoutSec=0
    RestartSec=2
    Restart=always
    
    
    
    StartLimitBurst=3
    
    
    StartLimitInterval=60s
    
    
    LimitNOFILE=infinity
    LimitNPROC=infinity
    LimitCORE=infinity
    
    
    TasksMax=infinity
    
    
    Delegate=yes
    
    
    KillMode=process
    OOMScoreAdjust=-500
    
    [Install]
    WantedBy=multi-user.target
    [root@longxi-master201 ~]#
    
    

    搜索OpenKruise仓库中的Charts

可以看到已经存在

image-20240717141947833

由于本次部署在K8S 1.27版本集群,并使用cri-dockerd,所以手动指定CRI。
注意:如果是1.24以下,则不需要,因为默认就是docker

helm install kruise openkruise/kruise --version 1.6.3 --set daemon.socketLocation=/var/run --set daemon.socketFile=cri-dockerd.sock


helm install kruise openkruise/kruise --version 1.6.3 --set daemon.socketLocation=/var/run --set daemon.socketFile=cri-dockerd.sock

image-20240717142010412

查看一下

helm list

image-20240717142035027

kubectl  -n kruise-system get all

可以看到都已经运行起来了

image-20240717142057458

二、OpenKruise使用案例

1. 部署应用
mkdir yaml && cd yaml
vim 01-ok.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  name: nginxweb1
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginxweb1
  template:
    metadata:
      labels:
        app: nginxweb1
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

应用yaml文件并查看

kubectl apply -f 01-ok.yaml
kubectl get clonesets

image-20240717142138585

kubectl get all

image-20240717142206343

创建成功之后通过 kubectl get all命令查看对应的信息,可以发现cloneset- controller 是直接创建的 Pod,而原生的Deployment 是通过 ReplicaSet 去创建的 Pod

2. 应用扩容
vim 02-ok.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  name: nginxweb1
  namespace: default
spec:
  minReadySeconds: 30
  scaleStrategy:
    maxUnavailable: 1
  replicas: 5
  selector:
    matchLabels:
      app: nginxweb1
  template:
    metadata:
      labels:
        app: nginxweb1
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

minReadySeconds: 30 创建了一个pod之后30s才会创建第二个
应用yaml文件并持续查看
注意: watch是持续查看 ctrl+c退出

kubectl apply -f 02-ok.yaml
watch kubectl get pods

可以看到30s之后才创建出来的第二个

image-20240717142320144

kubectl get cloneset

image-20240717142335669

kubectl get pods

image-20240717142350723

3. 应用缩容
vim 03-ok.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  name: nginxweb1
  namespace: default
spec:
  minReadySeconds: 30
  scaleStrategy:
    maxUnavailable: 1
    podsToDelete:
    - nginxweb1-frcl2 # 可指定多个
  replicas: 4
  selector:
    matchLabels:
      app: nginxweb1
  template:
    metadata:
      labels:
        app: nginxweb1
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

缩容时, CloneSet可以指定一些pod删除,而 StatefulSet 或者 Deployment 做不到:
StatefulSet 是根据序号来删除 Pod,而 Deployment/ReplicaSet 目前只能根据控制器里定义的排序来删除。
而 CloneSet 允许用户在缩小 replicas 数量的同时,指定想要删除的 Pod 名字。
如果只是把name加入podsToDelete,而没有修改replicas的话,删完之后会再扩一个pod

kubectl apply -f 03-ok.yaml
kubectl get pods

可以看到指定的pod已经被删除

image-20240717175838141

image-20240717142535298

4. 原地升级

先查看一下pod内nginx的版本

kubectl exec -it nginxweb1-g44p9 -- nginx -v

image-20240717142554700

vim 04-ok.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  name: nginxweb1
  namespace: default
spec:
  minReadySeconds: 30
  updateStrategy: #添加更新策略
    type: InPlaceIfPossible
  scaleStrategy:
    maxUnavailable: 1
  replicas: 4
  selector:
    matchLabels:
      app: nginxweb1
  template:
    metadata:
      labels:
        app: nginxweb1
    spec:
      containers:
      - name: nginx
        image: nginx:latest #更换镜像版本
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

kubectl apply -f 04-ok.yaml

更新过程

watch kubectl get pods

image-20240717142635659

kubectl exec -it nginxweb1-g44p9 -- nginx -v

可以看到nginx版本已经更新成功

image-20240717142656770

image-20240717180101624

5. 灰度更新

通过灰度更新可以更新部分pod

vim 05-ok.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  name: nginxweb1
  namespace: default
spec:
  minReadySeconds: 30
  updateStrategy: # 添加更新策略 
    type: InPlaceIfPossible
    partition: 2 # 保留旧版本pod数量
  scaleStrategy:
    maxUnavailable: 1
  replicas: 4
  selector:
    matchLabels:
      app: nginxweb1
  template:
    metadata:
      labels:
        app: nginxweb1
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

kubectl get pods

image-20240717142744744

kubectl apply -f 05-ok.yaml
watch kubectl get pods 

image-20240717142806049

查看版本

kubectl exec -it nginxweb1-g44p9 -- nginx -v
kubectl exec -it nginxweb1-jjsjp -- nginx -v
kubectl exec -it nginxweb1-wr8h7 -- nginx -v
kubectl exec -it nginxweb1-zhqxj -- nginx -v



nginxweb1-89nkb   1/1     Running   1 (57s ago)     6m18s
nginxweb1-kmp4g   1/1     Running   1 (2m12s ago)   4m45s
nginxweb1-pb9qt   1/1     Running   1 (24s ago)     6m18s
nginxweb1-x9vbh   1/1     Running   1 (94s ago)     5m17s


kubectl exec -it nginxweb1-89nkb -- nginx -v
kubectl exec -it nginxweb1-kmp4g  -- nginx -v
kubectl exec -it nginxweb1-pb9qt -- nginx -v
kubectl exec -it nginxweb1-x9vbh -- nginx -v

我们会发现只更新了2个pod,还有2个pod没有更新。

image-20240717180330825

image-20240717142831456

完成

总结

OpenKruise 通过增强 Kubernetes 的能力,提供了更灵活、高效的应用管理方式。它特别适用于需要高级更新策略、高可用性和大规模部署的场景,是对 Kubernetes 原生功能的强有力补充。

# Kruise v1.7.0-alpha.1

## Configuration

The following table lists the configurable parameters of the kruise chart and their default values.

### manager parameters
| Parameter                                 | Description                                                  | Default                       |
| ----------------------------------------- | ------------------------------------------------------------ | ----------------------------- |
| `featureGates`                            | Feature gates for Kruise, empty string means all enabled     | ` `                           |
| `installation.namespace`                  | namespace for kruise installation                            | `kruise-system`               |
| `installation.createNamespace`            | Whether to create the installation.namespace                 | `true`                        |
| `manager.log.level`                       | Log level that kruise-manager printed                        | `4`                           |
| `manager.replicas`                        | Replicas of kruise-controller-manager deployment             | `2`                           |
| `manager.image.repository`                | Repository for kruise-manager image                          | `openkruise/kruise-manager`   |
| `manager.image.tag`                       | Tag for kruise-manager image                                 | `v1.7.0-alpha.1`                      |
| `manager.resources.limits.cpu`            | CPU resource limit of kruise-manager container               | `200m`                        |
| `manager.resources.limits.memory`         | Memory resource limit of kruise-manager container            | `512Mi`                       |
| `manager.resources.requests.cpu`          | CPU resource request of kruise-manager container             | `100m`                        |
| `manager.resources.requests.memory`       | Memory resource request of kruise-manager container          | `256Mi`                       |
| `manager.metrics.port`                    | Port of metrics served                                       | `8080`                        |
| `manager.webhook.port`                    | Port of webhook served                                       | `9443`                        |
| `manager.pprofAddr`                       | Address of pprof served                                      | `localhost:8090`              |
| `manager.nodeAffinity`                    | Node affinity policy for kruise-manager pod                  | `{}`                          |
| `manager.nodeSelector`                    | Node labels for kruise-manager pod                           | `{}`                          |
| `manager.tolerations`                     | Tolerations for kruise-manager pod                           | `[]`                          |
| `webhookConfiguration.timeoutSeconds`     | The timeoutSeconds for all webhook configuration             | `30`                          |
| `crds.managed`                            | Kruise will not install CRDs with chart if this is false     | `true`                        |
| `manager.resyncPeriod`                    | Resync period of informer kruise-manager, defaults no resync | `0`                           |
| `manager.hostNetwork`                     | Whether kruise-manager pod should run with hostnetwork       | `false`                       |
| `imagePullSecrets`                        | The list of image pull secrets for kruise image              | `false`                       |
| `enableKubeCacheMutationDetector`         | Whether to enable KUBE_CACHE_MUTATION_DETECTOR               | `false`                       |

### daemon parameters
| Parameter                                 | Description                                                  | Default                       |
| ----------------------------------------- | ------------------------------------------------------------ | ----------------------------- |
| `daemon.extraEnvs`                        | Extra environment variables that will be pass onto pods      | `[]`                          |
| `daemon.log.level`                        | Log level that kruise-daemon printed                         | `4`                           |
| `daemon.port`                             | Port of metrics and healthz that kruise-daemon served        | `10221`                       |
| `daemon.pprofAddr`                        | Address of pprof served                                      | `localhost:10222`             |
| `daemon.resources.limits.cpu`             | CPU resource limit of kruise-daemon container                | `50m`                         |
| `daemon.resources.limits.memory`          | Memory resource limit of kruise-daemon container             | `128Mi`                       |
| `daemon.resources.requests.cpu`           | CPU resource request of kruise-daemon container              | `0`                           |
| `daemon.resources.requests.memory`        | Memory resource request of kruise-daemon container           | `0`                           |
| `daemon.affinity`                         | Affinity policy for kruise-daemon pod                        | `{}`                          |
| `daemon.socketLocation`                   | Location of the container manager control socket             | `/var/run`                    |
| `daemon.socketFile`                       | Specify the socket file name in `socketLocation` (if you are not using containerd/docker/pouch/cri-o) | ` ` |
| `daemon.credentialProvider.enable`        | Whether to enable credential provider for image pull job     | `false`                       |
| `daemon.credentialProvider.hostPath`      | credential provider plugin node dir, will volume mount into kruise-daemon | `credential-provider-plugin` |
| `daemon.credentialProvider.configmap`     | credential provider yaml configmap name in kruise-system ns  | `credential-provider-config`  |

Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,

### Optional: feature-gate

Feature-gate controls some influential features in Kruise:

| Name                                        | Description                                                                                                           | Default | Effect (if closed)                                                                                                |
|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------| ------- |-------------------------------------------------------------------------------------------------------------------|
| `PodWebhook`                                | Whether to open a webhook for Pod **create**                                                                          | `true`  | SidecarSet/KruisePodReadinessGate disabled                                                                        |
| `KruiseDaemon`                              | Whether to deploy `kruise-daemon` DaemonSet                                                                           | `true`  | ImagePulling/ContainerRecreateRequest disabled                                                                    |
| `DaemonWatchingPod`                         | Should each `kruise-daemon` watch pods on the same node                                                               | `true`  | For in-place update with same imageID or env from labels/annotations                                              |
| `CloneSetShortHash`                         | Enables CloneSet controller only set revision hash name to pod label                                                  | `false` | CloneSet name can not be longer than 54 characters                                                                |
| `KruisePodReadinessGate`                    | Enables Kruise webhook to inject 'KruisePodReady' readiness-gate to all Pods during creation                          | `false` | The readiness-gate will only be injected to Pods created by Kruise workloads                                      |
| `PreDownloadImageForInPlaceUpdate`          | Enables CloneSet controller to create ImagePullJobs to pre-download images for in-place update                        | `true` | No image pre-download for in-place update                                                                         |
| `CloneSetPartitionRollback`                 | Enables CloneSet controller to rollback Pods to currentRevision when number of updateRevision pods is bigger than (replicas - partition) | `false` | CloneSet will only update Pods to updateRevision                                                                  |
| `ResourcesDeletionProtection`               | Enables protection for resources deletion                                                                             | `true` | No protection for resources deletion                                                                              |
| `TemplateNoDefaults`                        | Whether to disable defaults injection for pod/pvc template in workloads                                               | `false` | Should not close this feature if it has open                                                                      |
| `PodUnavailableBudgetDeleteGate`            | Enables PodUnavailableBudget for pod deletion, eviction                                                               | `true` | No protection for pod deletion, eviction                                                                          |
| `PodUnavailableBudgetUpdateGate`            | Enables PodUnavailableBudget for pod.Spec update                                                                      | `false` | No protection for in-place update                                                                                 |
| `WorkloadSpread`                            | Enables WorkloadSpread to manage multi-domain and elastic deploy                                                      | `true` | WorkloadSpread disabled                                                                                           |
| `InPlaceUpdateEnvFromMetadata`              | Enables Kruise to in-place update a container in Pod when its env from labels/annotations changed and pod is in-place updating | `true` | Only container image can be in-place update                                                                       |
| `StatefulSetAutoDeletePVC`                  | Enables policies controlling deletion of PVCs created by a StatefulSet                                                | `true` | No deletion of PVCs by StatefulSet                                                                                |
| `PreDownloadImageForDaemonSetUpdate`        | Enables DaemonSet controller to create ImagePullJobs to pre-download images for in-place update                       | `false` | No image pre-download for in-place update                                                                         |
| `PodProbeMarkerGate`                        | Whether to turn on PodProbeMarker ability                                                                             | `true` | PodProbeMarker disabled                                                                                           |
| `SidecarSetPatchPodMetadataDefaultsAllowed` | Allow SidecarSet patch any annotations to Pod Object                                                                  | `false` | Annotations are not allowed to patch randomly and need to be configured via SidecarSet_PatchPodMetadata_WhiteList |
| `SidecarTerminator`                         | SidecarTerminator enables SidecarTerminator to stop sidecar containers when all main containers exited                | `false` | SidecarTerminator disabled                                                                                        |
| `CloneSetEventHandlerOptimization`          | CloneSetEventHandlerOptimization enable optimization for cloneset-controller to reduce the queuing frequency cased by pod update | `false` | optimization for cloneset-controller to reduce the queuing frequency cased by pod update disabled                 |
| `PreparingUpdateAsUpdate`                   | PreparingUpdateAsUpdate enable CloneSet/Advanced StatefulSet controller to regard preparing-update Pod as updated when calculating update/current revision during scaling. | `false` | Pods at preparing update state will be regarded as current revision instead of update revision                    |
| `ImagePullJobGate`                          | ImagePullJobGate enable imagepulljob-controller execute ImagePullJob | `false` | ImagePullJob and PreDownloadImageForInPlaceUpdate are disabled                                                    |
| `ResourceDistributionGate`                  | ResourceDistributionGate enable resourcedistribution-controller execute ResourceDistribution. | `false` | ResourceDistribution disabled                                                                                     |
| `DeletionProtectionForCRDCascadingGate`     | DeletionProtectionForCRDCascadingGate enable deletionProtection for crd Cascading | `false` | CustomResourceDefinition deletion protection disabled                                                             |

If you want to configure the feature-gate, just set the parameter when install or upgrade. Such as:

```bash
$ helm install kruise https://... --set featureGates="ResourcesDeletionProtection=true\,PreDownloadImageForInPlaceUpdate=true"
...
```

If you want to enable all feature-gates, set the parameter as `featureGates=AllAlpha=true`.

### Optional: the local image for China

If you are in China and have problem to pull image from official DockerHub, you can use the registry hosted on Alibaba Cloud:

```bash
$ helm install kruise https://... --set  manager.image.repository=openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager
...
```