From 0f9ec061574deeb5dd4f6eb3e43168cb1ab85c09 Mon Sep 17 00:00:00 2001 From: Yike Wang Date: Sun, 20 Aug 2023 11:18:31 +0800 Subject: [PATCH 1/2] Update charts and manifests version to 1.28 --- README.md | 1 + charts/vsphere-cpi/Chart.yaml | 4 +- charts/vsphere-cpi/README.md | 2 +- charts/vsphere-cpi/values.yaml | 2 +- .../book/tutorials/disable-node-deletion.yaml | 2 +- releases/README.md | 6 +- .../vsphere-cloud-controller-manager.yaml | 263 ++++++++++++++++++ 7 files changed, 272 insertions(+), 8 deletions(-) create mode 100644 releases/v1.28/vsphere-cloud-controller-manager.yaml diff --git a/README.md b/README.md index 5ddf6dc85..85cb04aa7 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Version matrix: | Kubernetes Version | vSphere Cloud Provider Release Version | Cloud Provider Branch | |--------------------|----------------------------------------|-----------------------| + | v1.28.X | v1.28.X | release-1.28 | | v1.27.X | v1.27.X | release-1.27 | | v1.26.X | v1.26.X | release-1.26 | | v1.25.X | v1.25.X | release-1.25 | diff --git a/charts/vsphere-cpi/Chart.yaml b/charts/vsphere-cpi/Chart.yaml index 82aed2225..f248773c2 100644 --- a/charts/vsphere-cpi/Chart.yaml +++ b/charts/vsphere-cpi/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: 1.27.0 +appVersion: 1.28.0 description: A Helm chart for vSphere Cloud Provider Interface Manager (CPI) name: vsphere-cpi -version: 1.27.0 +version: 1.28.0 keywords: - vsphere - vmware diff --git a/charts/vsphere-cpi/README.md b/charts/vsphere-cpi/README.md index c166f2b9f..32401abc0 100644 --- a/charts/vsphere-cpi/README.md +++ b/charts/vsphere-cpi/README.md @@ -149,7 +149,7 @@ helm repo add vsphere-cpi https://kubernetes.github.io/cloud-provider-vsphere helm repo update # Package CPI Chart -VERSION=1.27.0 +VERSION=1.28.0 cd charts helm package vsphere-cpi --version $VERSION --app-version $VERSION diff --git a/charts/vsphere-cpi/values.yaml b/charts/vsphere-cpi/values.yaml index 37ea8381e..d8bd298e8 100644 --- a/charts/vsphere-cpi/values.yaml +++ b/charts/vsphere-cpi/values.yaml @@ -55,7 +55,7 @@ serviceAccount: daemonset: annotations: {} image: gcr.io/cloud-provider-vsphere/cpi/release/manager - tag: v1.27.0 + tag: v1.28.0 pullPolicy: IfNotPresent dnsPolicy: ClusterFirst cmdline: diff --git a/docs/book/tutorials/disable-node-deletion.yaml b/docs/book/tutorials/disable-node-deletion.yaml index db57add83..036c47420 100644 --- a/docs/book/tutorials/disable-node-deletion.yaml +++ b/docs/book/tutorials/disable-node-deletion.yaml @@ -233,7 +233,7 @@ spec: priorityClassName: system-node-critical containers: - name: vsphere-cloud-controller-manager - image: gcr.io/cloud-provider-vsphere/cpi/release/manager:v1.27.0 + image: gcr.io/cloud-provider-vsphere/cpi/release/manager:v1.28.0 args: - --cloud-provider=vsphere - --v=2 diff --git a/releases/README.md b/releases/README.md index 00b3ff11d..04b69dd7c 100644 --- a/releases/README.md +++ b/releases/README.md @@ -8,14 +8,14 @@ Note that YAML files from [manifests/controller-manager repo](https://github.com ## Example workflow -In this tutorial, we will be installing the latest version of cloud provider vsphere(v1.27.0) freshly. If you have an older version of CPI already installed, the steps to deploy and upgrade CPI stay the same. With our `RollingUpdate` update strategy, after you update a DaemonSet template, old DaemonSet pods will be killed, and new DaemonSet pods will be created automatically. +In this tutorial, we will be installing the latest version of cloud provider vsphere(v1.28.0) freshly. If you have an older version of CPI already installed, the steps to deploy and upgrade CPI stay the same. With our `RollingUpdate` update strategy, after you update a DaemonSet template, old DaemonSet pods will be killed, and new DaemonSet pods will be created automatically. ### Step 1: find the kubernetes major version you are using -For example, the major version of '1.27.x' is '1.27', then run: +For example, the major version of '1.28.x' is '1.28', then run: ```bash -VERSION=1.27 +VERSION=1.28 wget https://raw.githubusercontent.com/kubernetes/cloud-provider-vsphere/release-$VERSION/releases/v$VERSION/vsphere-cloud-controller-manager.yaml ``` diff --git a/releases/v1.28/vsphere-cloud-controller-manager.yaml b/releases/v1.28/vsphere-cloud-controller-manager.yaml new file mode 100644 index 000000000..9cb4be8c4 --- /dev/null +++ b/releases/v1.28/vsphere-cloud-controller-manager.yaml @@ -0,0 +1,263 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cloud-controller-manager + labels: + vsphere-cpi-infra: service-account + component: cloud-controller-manager + namespace: kube-system +--- +apiVersion: v1 +kind: Secret +metadata: + name: vsphere-cloud-secret + labels: + vsphere-cpi-infra: secret + component: cloud-controller-manager + namespace: kube-system + # NOTE: this is just an example configuration, update with real values based on your environment +stringData: + 10.0.0.1.username: "" + 10.0.0.1.password: "" + 1.2.3.4.username: "" + 1.2.3.4.password: "" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: vsphere-cloud-config + labels: + vsphere-cpi-infra: config + component: cloud-controller-manager + namespace: kube-system +data: + # NOTE: this is just an example configuration, update with real values based on your environment + vsphere.conf: | + # Global properties in this section will be used for all specified vCenters unless overriden in VirtualCenter section. + global: + port: 443 + # set insecureFlag to true if the vCenter uses a self-signed cert + insecureFlag: true + # settings for using k8s secret + secretName: vsphere-cloud-secret + secretNamespace: kube-system + + # vcenter section + vcenter: + your-vcenter-name-here: + server: 10.0.0.1 + user: use-your-vcenter-user-here + password: use-your-vcenter-password-here + datacenters: + - hrwest + - hreast + could-be-a-tenant-label: + server: 1.2.3.4 + datacenters: + - mytenantdc + secretName: cpi-engineering-secret + secretNamespace: kube-system + + # labels for regions and zones + labels: + region: k8s-region + zone: k8s-zone +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: servicecatalog.k8s.io:apiserver-authentication-reader + labels: + vsphere-cpi-infra: role-binding + component: cloud-controller-manager + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - apiGroup: "" + kind: ServiceAccount + name: cloud-controller-manager + namespace: kube-system + - apiGroup: "" + kind: User + name: cloud-controller-manager +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:cloud-controller-manager + labels: + vsphere-cpi-infra: cluster-role-binding + component: cloud-controller-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:cloud-controller-manager +subjects: + - kind: ServiceAccount + name: cloud-controller-manager + namespace: kube-system + - kind: User + name: cloud-controller-manager +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:cloud-controller-manager + labels: + vsphere-cpi-infra: role + component: cloud-controller-manager +rules: + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update + - apiGroups: + - "" + resources: + - nodes + verbs: + - "*" + - apiGroups: + - "" + resources: + - nodes/status + verbs: + - patch + - apiGroups: + - "" + resources: + - services + verbs: + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - services/status + verbs: + - patch + - apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - endpoints + verbs: + - create + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - create + - get + - list + - watch + - update +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: vsphere-cloud-controller-manager + labels: + component: cloud-controller-manager + tier: control-plane + namespace: kube-system +spec: + selector: + matchLabels: + name: vsphere-cloud-controller-manager + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + name: vsphere-cloud-controller-manager + component: cloud-controller-manager + tier: control-plane + spec: + tolerations: + - key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + - key: node.kubernetes.io/not-ready + effect: NoSchedule + operator: Exists + securityContext: + runAsUser: 1001 + serviceAccountName: cloud-controller-manager + priorityClassName: system-node-critical + containers: + - name: vsphere-cloud-controller-manager + image: gcr.io/cloud-provider-vsphere/cpi/release/manager:v1.28.0 + args: + - --cloud-provider=vsphere + - --v=2 + - --cloud-config=/etc/cloud/vsphere.conf + volumeMounts: + - mountPath: /etc/cloud + name: vsphere-config-volume + readOnly: true + resources: + requests: + cpu: 200m + hostNetwork: true + volumes: + - name: vsphere-config-volume + configMap: + name: vsphere-cloud-config + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + - matchExpressions: + - key: node-role.kubernetes.io/master + operator: Exists From b8e4aa9939f5466cb65502fbb3984fc3bf108f98 Mon Sep 17 00:00:00 2001 From: Yike Wang Date: Fri, 25 Aug 2023 10:05:29 +0800 Subject: [PATCH 2/2] Release 1.28 helm charts --- charts/vsphere-cpi-1.28.0.tgz | Bin 0 -> 6716 bytes index.yaml | 31 +++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 charts/vsphere-cpi-1.28.0.tgz diff --git a/charts/vsphere-cpi-1.28.0.tgz b/charts/vsphere-cpi-1.28.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..96c3a147a94753cc3f2e7dbce7cc266c705342ba GIT binary patch literal 6716 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 S=l=r$0RR8-5Y%7*i~s