mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-01-27 10:18:39 +00:00
[kube-ovn] Update and patch Kube-OVN (#1363)
## What this PR does This patch updates Kube-OVN to 1.14.5 and patches the northd leader check to test against all northd endpoints instead of just the first one marked as ready. ### Release note ```release-note [kube-ovn, fix] Update Kube-OVN and improve northd leader detection. ``` Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
This commit is contained in:
@@ -8,9 +8,9 @@ include ../../../scripts/package.mk
|
||||
|
||||
update:
|
||||
rm -rf charts && mkdir -p charts/kube-ovn
|
||||
tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/kubeovn/kube-ovn | awk -F'[/^]' '{print $$3}' | grep '^v1\.13\.' | tail -n1 ) && \
|
||||
tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/kubeovn/kube-ovn | awk -F'[/^]' '{print $$3}' | grep '^v1\.14\.' | tail -n1 ) && \
|
||||
curl -sSL https://github.com/kubeovn/kube-ovn/archive/refs/tags/$${tag}.tar.gz | \
|
||||
tar xzvf - --strip 1 kube-ovn-$${tag#*v}/charts
|
||||
tar xzvf - --strip 1 kube-ovn-$${tag#*v}/charts/kube-ovn
|
||||
patch --no-backup-if-mismatch -p4 < patches/cozyconfig.diff
|
||||
patch --no-backup-if-mismatch -p4 < patches/mtu.diff
|
||||
version=$$(awk '$$1 == "version:" {print $$2}' charts/kube-ovn/Chart.yaml) && \
|
||||
|
||||
@@ -15,12 +15,12 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: v1.13.14
|
||||
version: v1.14.5
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.13.14"
|
||||
appVersion: "1.14.5"
|
||||
|
||||
kubeVersion: ">= 1.23.0-0"
|
||||
kubeVersion: ">= 1.29.0-0"
|
||||
|
||||
@@ -20,6 +20,9 @@ Get IP-addresses of master nodes
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if and (eq (len $ips) 0) (not $.Values.MASTER_NODES) -}}
|
||||
{{- fail (printf "No nodes found with label '%s'. Please check your MASTER_NODES_LABEL configuration or ensure master nodes are properly labeled." $.Values.MASTER_NODES_LABEL) -}}
|
||||
{{- end -}}
|
||||
{{ join "," $ips }}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
@@ -115,6 +115,9 @@ spec:
|
||||
- --enable-anp={{- .Values.func.ENABLE_ANP }}
|
||||
- --ovsdb-con-timeout={{- .Values.func.OVSDB_CON_TIMEOUT }}
|
||||
- --ovsdb-inactivity-timeout={{- .Values.func.OVSDB_INACTIVITY_TIMEOUT }}
|
||||
- --enable-live-migration-optimize={{- .Values.func.ENABLE_LIVE_MIGRATION_OPTIMIZE }}
|
||||
- --enable-ovn-lb-prefer-local={{- .Values.func.ENABLE_OVN_LB_PREFER_LOCAL }}
|
||||
- --image={{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}
|
||||
securityContext:
|
||||
runAsUser: {{ include "kubeovn.runAsUser" . }}
|
||||
privileged: false
|
||||
|
||||
@@ -3,7 +3,7 @@ kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: ovn-ic-controller
|
||||
namespace: kube-system
|
||||
namespace: {{ .Values.namespace }}
|
||||
annotations:
|
||||
kubernetes.io/description: |
|
||||
OVN IC Client
|
||||
@@ -109,7 +109,9 @@ spec:
|
||||
name: kube-ovn-log
|
||||
nodeSelector:
|
||||
kubernetes.io/os: "linux"
|
||||
kube-ovn/role: "master"
|
||||
{{- with splitList "=" .Values.MASTER_NODES_LABEL }}
|
||||
{{ index . 0 }}: "{{ if eq (len .) 2 }}{{ index . 1 }}{{ end }}"
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: host-run-ovn
|
||||
hostPath:
|
||||
|
||||
@@ -823,6 +823,378 @@ spec:
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: vpc-egress-gateways.kubeovn.io
|
||||
spec:
|
||||
group: kubeovn.io
|
||||
names:
|
||||
plural: vpc-egress-gateways
|
||||
singular: vpc-egress-gateway
|
||||
shortNames:
|
||||
- vpc-egress-gw
|
||||
- veg
|
||||
kind: VpcEgressGateway
|
||||
listKind: VpcEgressGatewayList
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.vpc
|
||||
name: VPC
|
||||
type: string
|
||||
- jsonPath: .spec.replicas
|
||||
name: REPLICAS
|
||||
type: integer
|
||||
- jsonPath: .spec.bfd.enabled
|
||||
name: BFD ENABLED
|
||||
type: boolean
|
||||
- jsonPath: .spec.externalSubnet
|
||||
name: EXTERNAL SUBNET
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
name: PHASE
|
||||
type: string
|
||||
- jsonPath: .status.ready
|
||||
name: READY
|
||||
type: boolean
|
||||
- jsonPath: .status.internalIPs
|
||||
name: INTERNAL IPS
|
||||
priority: 1
|
||||
type: string
|
||||
- jsonPath: .status.externalIPs
|
||||
name: EXTERNAL IPS
|
||||
priority: 1
|
||||
type: string
|
||||
- jsonPath: .status.workload.nodes
|
||||
name: WORKING NODES
|
||||
priority: 1
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
name: v1
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
scale:
|
||||
# specReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Spec.Replicas.
|
||||
specReplicasPath: .spec.replicas
|
||||
# statusReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Replicas.
|
||||
statusReplicasPath: .status.replicas
|
||||
# labelSelectorPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Selector.
|
||||
labelSelectorPath: .status.labelSelector
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
properties:
|
||||
replicas:
|
||||
type: integer
|
||||
format: int32
|
||||
labelSelector:
|
||||
type: string
|
||||
conditions:
|
||||
items:
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- lastUpdateTime
|
||||
- observedGeneration
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
internalIPs:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
externalIPs:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
phase:
|
||||
type: string
|
||||
default: Pending
|
||||
enum:
|
||||
- Pending
|
||||
- Processing
|
||||
- Completed
|
||||
ready:
|
||||
type: boolean
|
||||
default: false
|
||||
workload:
|
||||
type: object
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
nodes:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- conditions
|
||||
- phase
|
||||
type: object
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- externalSubnet
|
||||
x-kubernetes-validations:
|
||||
- rule: "!has(self.internalIPs) || size(self.internalIPs) == 0 || size(self.internalIPs) >= self.replicas"
|
||||
message: 'Size of Internal IPs MUST be equal to or greater than Replicas'
|
||||
fieldPath: ".internalIPs"
|
||||
- rule: "!has(self.externalIPs) || size(self.externalIPs) == 0 || size(self.externalIPs) >= self.replicas"
|
||||
message: 'Size of External IPs MUST be equal to or greater than Replicas'
|
||||
fieldPath: ".externalIPs"
|
||||
- rule: "size(self.policies) != 0 || size(self.selectors) != 0"
|
||||
message: 'Each VPC Egress Gateway MUST have at least one policy or selector'
|
||||
properties:
|
||||
replicas:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 1
|
||||
minimum: 0
|
||||
maximum: 10
|
||||
prefix:
|
||||
type: string
|
||||
anyOf:
|
||||
- pattern: ^$
|
||||
- pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*[-\.]?$
|
||||
x-kubernetes-validations:
|
||||
- rule: "self == oldSelf"
|
||||
message: "This field is immutable."
|
||||
vpc:
|
||||
type: string
|
||||
internalSubnet:
|
||||
type: string
|
||||
externalSubnet:
|
||||
type: string
|
||||
internalIPs:
|
||||
items:
|
||||
type: string
|
||||
oneOf:
|
||||
- format: ipv4
|
||||
- format: ipv6
|
||||
- pattern: ^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5]),((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))$
|
||||
- pattern: ^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:))),(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
externalIPs:
|
||||
items:
|
||||
type: string
|
||||
oneOf:
|
||||
- format: ipv4
|
||||
- format: ipv6
|
||||
- pattern: ^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5]),((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))$
|
||||
- pattern: ^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:))),(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
image:
|
||||
type: string
|
||||
bfd:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
default: false
|
||||
minRX:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 1000
|
||||
minTX:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 1000
|
||||
multiplier:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 3
|
||||
selectors:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
namespaceSelector:
|
||||
type: object
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
matchExpressions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
values:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
x-kubernetes-validations:
|
||||
- rule: "size(self.matchLabels) != 0 || size(self.matchExpressions) != 0"
|
||||
message: 'Each namespace selector MUST have at least one matchLabels or matchExpressions'
|
||||
podSelector:
|
||||
type: object
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
matchExpressions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
values:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
x-kubernetes-validations:
|
||||
- rule: "size(self.matchLabels) != 0 || size(self.matchExpressions) != 0"
|
||||
message: 'Each pod selector MUST have at least one matchLabels or matchExpressions'
|
||||
policies:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
snat:
|
||||
type: boolean
|
||||
default: false
|
||||
ipBlocks:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
items:
|
||||
type: string
|
||||
anyOf:
|
||||
- format: ipv4
|
||||
- format: ipv6
|
||||
- format: cidr
|
||||
subnets:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
items:
|
||||
type: string
|
||||
minLength: 1
|
||||
x-kubernetes-validations:
|
||||
- rule: "size(self.ipBlocks) != 0 || size(self.subnets) != 0"
|
||||
message: 'Each policy MUST have at least one ipBlock or subnet'
|
||||
trafficPolicy:
|
||||
type: string
|
||||
enum:
|
||||
- Local
|
||||
- Cluster
|
||||
default: Cluster
|
||||
nodeSelector:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
matchExpressions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
enum:
|
||||
- In
|
||||
- NotIn
|
||||
- Exists
|
||||
- DoesNotExist
|
||||
- Gt
|
||||
- Lt
|
||||
values:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
matchFields:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
enum:
|
||||
- In
|
||||
- NotIn
|
||||
- Exists
|
||||
- DoesNotExist
|
||||
- Gt
|
||||
- Lt
|
||||
values:
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: iptables-eips.kubeovn.io
|
||||
spec:
|
||||
@@ -1293,6 +1665,9 @@ spec:
|
||||
- jsonPath: .status.vpc
|
||||
name: Vpc
|
||||
type: string
|
||||
- jsonPath: .spec.type
|
||||
name: Type
|
||||
type: string
|
||||
- jsonPath: .status.v4Eip
|
||||
name: V4Eip
|
||||
type: string
|
||||
@@ -1357,6 +1732,8 @@ spec:
|
||||
type: string
|
||||
ipType:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
ipName:
|
||||
type: string
|
||||
vpc:
|
||||
@@ -1665,6 +2042,51 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
bfdPort:
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
default: false
|
||||
ip:
|
||||
type: string
|
||||
anyOf:
|
||||
- pattern: ^$
|
||||
- pattern: ^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$
|
||||
- pattern: ^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))$
|
||||
- pattern: ^(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5]),((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:)))$
|
||||
- pattern: ^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|:))),(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])$
|
||||
nodeSelector:
|
||||
properties:
|
||||
matchExpressions:
|
||||
items:
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
operator:
|
||||
type: string
|
||||
enum:
|
||||
- In
|
||||
- NotIn
|
||||
- Exists
|
||||
- DoesNotExist
|
||||
values:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: object
|
||||
type: array
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-validations:
|
||||
- rule: "self.enabled == false || self.ip != ''"
|
||||
message: 'Port IP must be set when BFD Port is enabled'
|
||||
type: object
|
||||
status:
|
||||
properties:
|
||||
@@ -1721,6 +2143,17 @@ spec:
|
||||
type: string
|
||||
sctpSessionLoadBalancer:
|
||||
type: string
|
||||
bfdPort:
|
||||
type: object
|
||||
properties:
|
||||
ip:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
nodes:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
@@ -1837,18 +2270,12 @@ spec:
|
||||
- name: Mac
|
||||
type: string
|
||||
jsonPath: .status.mac
|
||||
- name: PMac
|
||||
type: string
|
||||
jsonPath: .spec.parentMac
|
||||
- name: Subnet
|
||||
type: string
|
||||
jsonPath: .spec.subnet
|
||||
- jsonPath: .status.ready
|
||||
name: Ready
|
||||
type: boolean
|
||||
- jsonPath: .status.type
|
||||
name: Type
|
||||
- name: Type
|
||||
type: string
|
||||
jsonPath: .status.type
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
@@ -1866,12 +2293,6 @@ spec:
|
||||
type: string
|
||||
mac:
|
||||
type: string
|
||||
pv4ip:
|
||||
type: string
|
||||
pv6ip:
|
||||
type: string
|
||||
pmac:
|
||||
type: string
|
||||
selector:
|
||||
type: array
|
||||
items:
|
||||
@@ -1912,12 +2333,6 @@ spec:
|
||||
type: string
|
||||
v6ip:
|
||||
type: string
|
||||
parentV4ip:
|
||||
type: string
|
||||
parentMac:
|
||||
type: string
|
||||
parentV6ip:
|
||||
type: string
|
||||
selector:
|
||||
type: array
|
||||
items:
|
||||
@@ -2196,6 +2611,8 @@ spec:
|
||||
type: boolean
|
||||
enableMulticastSnoop:
|
||||
type: boolean
|
||||
enableExternalLBAddress:
|
||||
type: boolean
|
||||
routeTable:
|
||||
type: string
|
||||
namespaceSelectors:
|
||||
@@ -2375,6 +2792,8 @@ spec:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
conflict:
|
||||
type: boolean
|
||||
additionalPrinterColumns:
|
||||
- name: ID
|
||||
type: string
|
||||
@@ -2382,6 +2801,9 @@ spec:
|
||||
- name: Provider
|
||||
type: string
|
||||
jsonPath: .spec.provider
|
||||
- name: conflict
|
||||
type: boolean
|
||||
jsonPath: .status.conflict
|
||||
scope: Cluster
|
||||
names:
|
||||
plural: vlans
|
||||
|
||||
@@ -13,6 +13,8 @@ rules:
|
||||
- vpcs/status
|
||||
- vpc-nat-gateways
|
||||
- vpc-nat-gateways/status
|
||||
- vpc-egress-gateways
|
||||
- vpc-egress-gateways/status
|
||||
- subnets
|
||||
- subnets/status
|
||||
- ippools
|
||||
@@ -98,6 +100,18 @@ rules:
|
||||
- daemonsets
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- deployments
|
||||
- deployments/scale
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- delete
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
@@ -121,12 +135,18 @@ rules:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- discovery.k8s.io
|
||||
resources:
|
||||
- endpointslices
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- statefulsets
|
||||
- deployments
|
||||
- deployments/scale
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
@@ -155,6 +175,7 @@ rules:
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "policy.networking.k8s.io"
|
||||
resources:
|
||||
@@ -240,9 +261,14 @@ rules:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- discovery.k8s.io
|
||||
resources:
|
||||
- endpointslices
|
||||
verbs:
|
||||
- list
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
@@ -278,6 +304,7 @@ rules:
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
- services
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
|
||||
@@ -31,7 +31,7 @@ spec:
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: openvswitch
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}-dpdk
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.DPDK_IMAGE_TAG }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command: ["/kube-ovn/start-ovs-dpdk-v2.sh"]
|
||||
securityContext:
|
||||
|
||||
@@ -38,11 +38,7 @@ spec:
|
||||
hostPID: true
|
||||
initContainers:
|
||||
- name: hostpath-init
|
||||
{{- if .Values.DPDK }}
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.dpdkRepository }}:{{ .Values.DPDK_VERSION }}-{{ .Values.global.images.kubeovn.tag }}
|
||||
{{- else }}
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- sh
|
||||
@@ -82,17 +78,9 @@ spec:
|
||||
name: host-log-ovs
|
||||
containers:
|
||||
- name: openvswitch
|
||||
{{- if .Values.DPDK }}
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.dpdkRepository }}:{{ .Values.DPDK_VERSION }}-{{ .Values.global.images.kubeovn.tag }}
|
||||
{{- else }}
|
||||
image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- if .Values.DPDK }}
|
||||
command: ["/kube-ovn/start-ovs-dpdk.sh"]
|
||||
{{- else }}
|
||||
command: ["/kube-ovn/start-ovs.sh"]
|
||||
{{- end }}
|
||||
securityContext:
|
||||
runAsUser: {{ include "kubeovn.runAsUser" . }}
|
||||
privileged: false
|
||||
@@ -156,59 +144,30 @@ spec:
|
||||
- mountPath: /var/run/containerd
|
||||
name: cruntime
|
||||
readOnly: true
|
||||
{{- if .Values.DPDK }}
|
||||
- mountPath: /opt/ovs-config
|
||||
name: host-config-ovs
|
||||
- mountPath: /dev/hugepages
|
||||
name: hugepage
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
{{- if .Values.DPDK }}
|
||||
command:
|
||||
- bash
|
||||
- /kube-ovn/ovs-dpdk-healthcheck.sh
|
||||
{{- else }}
|
||||
command:
|
||||
- bash
|
||||
- /kube-ovn/ovs-healthcheck.sh
|
||||
{{- end }}
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 45
|
||||
livenessProbe:
|
||||
exec:
|
||||
{{- if .Values.DPDK }}
|
||||
command:
|
||||
- bash
|
||||
- /kube-ovn/ovs-dpdk-healthcheck.sh
|
||||
{{- else }}
|
||||
command:
|
||||
- bash
|
||||
- /kube-ovn/ovs-healthcheck.sh
|
||||
{{- end }}
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
timeoutSeconds: 45
|
||||
resources:
|
||||
requests:
|
||||
{{- if .Values.DPDK }}
|
||||
cpu: {{ .Values.DPDK_CPU }}
|
||||
memory: {{ .Values.DPDK_MEMORY }}
|
||||
{{- else }}
|
||||
cpu: {{ index .Values "ovs-ovn" "requests" "cpu" }}
|
||||
memory: {{ index .Values "ovs-ovn" "requests" "memory" }}
|
||||
{{- end }}
|
||||
limits:
|
||||
{{- if .Values.DPDK }}
|
||||
cpu: {{ .Values.DPDK_CPU }}
|
||||
memory: {{ .Values.DPDK_MEMORY }}
|
||||
hugepages-1Gi: 1Gi
|
||||
{{- else }}
|
||||
cpu: {{ index .Values "ovs-ovn" "limits" "cpu" }}
|
||||
memory: {{ index .Values "ovs-ovn" "limits" "memory" }}
|
||||
{{- end }}
|
||||
nodeSelector:
|
||||
kubernetes.io/os: "linux"
|
||||
volumes:
|
||||
@@ -242,12 +201,3 @@ spec:
|
||||
- hostPath:
|
||||
path: /var/run/containerd
|
||||
name: cruntime
|
||||
{{- if .Values.DPDK }}
|
||||
- name: host-config-ovs
|
||||
hostPath:
|
||||
path: /opt/ovs-config
|
||||
type: DirectoryOrCreate
|
||||
- name: hugepage
|
||||
emptyDir:
|
||||
medium: HugePages
|
||||
{{- end }}
|
||||
|
||||
@@ -129,6 +129,18 @@ spec:
|
||||
limits:
|
||||
cpu: {{ index .Values "kube-ovn-pinger" "limits" "cpu" }}
|
||||
memory: {{ index .Values "kube-ovn-pinger" "limits" "memory" }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: 8080
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
nodeSelector:
|
||||
kubernetes.io/os: "linux"
|
||||
volumes:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kube-ovn-pre-delete-hook
|
||||
name: kube-ovn-post-delete-hook
|
||||
namespace: {{ .Values.namespace }}
|
||||
annotations:
|
||||
# This is what defines this resource as a hook. Without this line, the
|
||||
# job is considered part of the release.
|
||||
"helm.sh/hook": pre-delete
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "1"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
---
|
||||
@@ -17,15 +17,17 @@ metadata:
|
||||
rbac.authorization.k8s.io/system-only: "true"
|
||||
# This is what defines this resource as a hook. Without this line, the
|
||||
# job is considered part of the release.
|
||||
"helm.sh/hook": pre-delete
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "2"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
name: system:kube-ovn-pre-delete-hook
|
||||
name: system:kube-ovn-post-delete-hook
|
||||
rules:
|
||||
- apiGroups:
|
||||
- kubeovn.io
|
||||
resources:
|
||||
- subnets
|
||||
- vpcs
|
||||
- ips
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
@@ -34,26 +36,26 @@ rules:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kube-ovn-pre-delete-hook
|
||||
name: kube-ovn-post-delete-hook
|
||||
annotations:
|
||||
# This is what defines this resource as a hook. Without this line, the
|
||||
# job is considered part of the release.
|
||||
"helm.sh/hook": pre-delete
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "3"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
roleRef:
|
||||
name: system:kube-ovn-pre-delete-hook
|
||||
name: system:kube-ovn-post-delete-hook
|
||||
kind: ClusterRole
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kube-ovn-pre-delete-hook
|
||||
name: kube-ovn-post-delete-hook
|
||||
namespace: {{ .Values.namespace }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "{{ .Chart.Name }}-pre-delete-hook"
|
||||
name: "{{ .Chart.Name }}-post-delete-hook"
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
|
||||
@@ -63,7 +65,7 @@ metadata:
|
||||
annotations:
|
||||
# This is what defines this resource as a hook. Without this line, the
|
||||
# job is considered part of the release.
|
||||
"helm.sh/hook": pre-delete
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "4"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
spec:
|
||||
@@ -75,7 +77,7 @@ spec:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name | quote }}
|
||||
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: kube-ovn-pre-delete-hook
|
||||
app: kube-ovn-post-delete-hook
|
||||
component: job
|
||||
spec:
|
||||
tolerations:
|
||||
@@ -91,7 +93,7 @@ spec:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- kube-ovn-pre-delete-hook
|
||||
- kube-ovn-post-delete-hook
|
||||
- key: component
|
||||
operator: In
|
||||
values:
|
||||
@@ -100,8 +102,8 @@ spec:
|
||||
hostNetwork: true
|
||||
nodeSelector:
|
||||
kubernetes.io/os: "linux"
|
||||
serviceAccount: kube-ovn-pre-delete-hook
|
||||
serviceAccountName: kube-ovn-pre-delete-hook
|
||||
serviceAccount: kube-ovn-post-delete-hook
|
||||
serviceAccountName: kube-ovn-post-delete-hook
|
||||
containers:
|
||||
- name: remove-subnet-finalizer
|
||||
image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}"
|
||||
@@ -113,7 +115,7 @@ spec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- /kube-ovn/remove-subnet-finalizer.sh 2>&1 | tee -a /var/log/kube-ovn/remove-subnet-finalizer.log
|
||||
- /kube-ovn/remove-finalizer.sh 2>&1 | tee -a /var/log/kube-ovn/remove-finalizer.log
|
||||
volumeMounts:
|
||||
- mountPath: /var/log/kube-ovn
|
||||
name: kube-ovn-log
|
||||
@@ -14,6 +14,6 @@ kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: ovn-vpc-nat-gw-config
|
||||
namespace: kube-system
|
||||
namespace: {{ .Values.namespace }}
|
||||
data:
|
||||
enable-vpc-nat-gw: "{{ .Values.func.ENABLE_NAT_GW }}"
|
||||
enable-vpc-nat-gw: "{{ .Values.func.ENABLE_NAT_GW }}"
|
||||
|
||||
@@ -8,9 +8,8 @@ global:
|
||||
images:
|
||||
kubeovn:
|
||||
repository: kube-ovn
|
||||
dpdkRepository: kube-ovn-dpdk
|
||||
vpcRepository: vpc-nat-gateway
|
||||
tag: v1.13.14
|
||||
tag: v1.14.5
|
||||
support_arm: true
|
||||
thirdparty: true
|
||||
|
||||
@@ -58,7 +57,7 @@ networking:
|
||||
func:
|
||||
ENABLE_LB: true
|
||||
ENABLE_NP: true
|
||||
ENABLE_EXTERNAL_VPC: true
|
||||
ENABLE_EXTERNAL_VPC: false
|
||||
HW_OFFLOAD: false
|
||||
ENABLE_LB_SVC: false
|
||||
ENABLE_KEEP_VM_IP: true
|
||||
@@ -78,6 +77,7 @@ func:
|
||||
OVSDB_CON_TIMEOUT: 3
|
||||
OVSDB_INACTIVITY_TIMEOUT: 10
|
||||
ENABLE_LIVE_MIGRATION_OPTIMIZE: true
|
||||
ENABLE_OVN_LB_PREFER_LOCAL: false
|
||||
|
||||
ipv4:
|
||||
PINGER_EXTERNAL_ADDRESS: "1.1.1.1"
|
||||
@@ -133,10 +133,7 @@ fullnameOverride: ""
|
||||
HYBRID_DPDK: false
|
||||
HUGEPAGE_SIZE_TYPE: hugepages-2Mi # Default
|
||||
HUGEPAGES: 1Gi
|
||||
|
||||
# DPDK
|
||||
DPDK: false
|
||||
DPDK_VERSION: "19.11"
|
||||
DPDK_IMAGE_TAG: "v1.14.0-dpdk"
|
||||
DPDK_CPU: "1000m" # Default CPU configuration
|
||||
DPDK_MEMORY: "2Gi" # Default Memory configuration
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# syntax = docker/dockerfile:experimental
|
||||
ARG VERSION=v1.13.14
|
||||
ARG VERSION=v1.14.5
|
||||
ARG BASE_TAG=$VERSION
|
||||
|
||||
FROM golang:1.23-bookworm as builder
|
||||
FROM golang:1.24-bookworm as builder
|
||||
|
||||
ARG TAG=v1.13.14
|
||||
ARG TAG=v1.14.5
|
||||
RUN git clone --branch ${TAG} --depth 1 https://github.com/kubeovn/kube-ovn /source
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
diff --git a/mocks/pkg/ovs/interface.go b/mocks/pkg/ovs/interface.go
|
||||
index e9c472bee..59076f9ed 100644
|
||||
--- a/mocks/pkg/ovs/interface.go
|
||||
+++ b/mocks/pkg/ovs/interface.go
|
||||
@@ -10,6 +10,7 @@
|
||||
package ovs
|
||||
|
||||
import (
|
||||
+ context "context"
|
||||
reflect "reflect"
|
||||
|
||||
v1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
|
||||
@@ -3322,6 +3323,20 @@ func (mr *MockNbClientMockRecorder) DeleteSecurityGroup(sgName any) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSecurityGroup", reflect.TypeOf((*MockNbClient)(nil).DeleteSecurityGroup), sgName)
|
||||
}
|
||||
|
||||
+// Echo mocks base method.
|
||||
+func (m *MockNbClient) Echo(arg0 context.Context) error {
|
||||
+ m.ctrl.T.Helper()
|
||||
+ ret := m.ctrl.Call(m, "Echo", arg0)
|
||||
+ ret0, _ := ret[0].(error)
|
||||
+ return ret0
|
||||
+}
|
||||
+
|
||||
+// Echo indicates an expected call of Echo.
|
||||
+func (mr *MockNbClientMockRecorder) Echo(arg0 any) *gomock.Call {
|
||||
+ mr.mock.ctrl.T.Helper()
|
||||
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Echo", reflect.TypeOf((*MockNbClient)(nil).Echo), arg0)
|
||||
+}
|
||||
+
|
||||
// EnablePortLayer2forward mocks base method.
|
||||
func (m *MockNbClient) EnablePortLayer2forward(lspName string) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -4770,6 +4785,20 @@ func (mr *MockSbClientMockRecorder) GetAllChassisByHost(nodeName any) *gomock.Ca
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllChassisByHost", reflect.TypeOf((*MockSbClient)(nil).GetAllChassisByHost), nodeName)
|
||||
}
|
||||
|
||||
+// Echo mocks base method.
|
||||
+func (m *MockSbClient) Echo(arg0 context.Context) error {
|
||||
+ m.ctrl.T.Helper()
|
||||
+ ret := m.ctrl.Call(m, "Echo", arg0)
|
||||
+ ret0, _ := ret[0].(error)
|
||||
+ return ret0
|
||||
+}
|
||||
+
|
||||
+// Echo indicates an expected call of Echo.
|
||||
+func (mr *MockSbClientMockRecorder) Echo(arg0 any) *gomock.Call {
|
||||
+ mr.mock.ctrl.T.Helper()
|
||||
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Echo", reflect.TypeOf((*MockSbClient)(nil).Echo), arg0)
|
||||
+}
|
||||
+
|
||||
// GetChassis mocks base method.
|
||||
func (m *MockSbClient) GetChassis(chassisName string, ignoreNotFound bool) (*ovnsb.Chassis, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -4915,6 +4944,20 @@ func (m *MockCommon) EXPECT() *MockCommonMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
+// Echo mocks base method.
|
||||
+func (m *MockCommon) Echo(arg0 context.Context) error {
|
||||
+ m.ctrl.T.Helper()
|
||||
+ ret := m.ctrl.Call(m, "Echo", arg0)
|
||||
+ ret0, _ := ret[0].(error)
|
||||
+ return ret0
|
||||
+}
|
||||
+
|
||||
+// Echo indicates an expected call of Echo.
|
||||
+func (mr *MockCommonMockRecorder) Echo(arg0 any) *gomock.Call {
|
||||
+ mr.mock.ctrl.T.Helper()
|
||||
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Echo", reflect.TypeOf((*MockCommon)(nil).Echo), arg0)
|
||||
+}
|
||||
+
|
||||
// GetEntityInfo mocks base method.
|
||||
func (m *MockCommon) GetEntityInfo(entity any) error {
|
||||
m.ctrl.T.Helper()
|
||||
diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go
|
||||
index cb594a4c8..a2a88eb06 100644
|
||||
--- a/pkg/controller/controller.go
|
||||
+++ b/pkg/controller/controller.go
|
||||
@@ -268,6 +268,9 @@ type Controller struct {
|
||||
cmInformerFactory kubeinformers.SharedInformerFactory
|
||||
kubeovnInformerFactory kubeovninformer.SharedInformerFactory
|
||||
anpInformerFactory anpinformer.SharedInformerFactory
|
||||
+
|
||||
+ // Database health check
|
||||
+ dbFailureCount int
|
||||
}
|
||||
|
||||
func newTypedRateLimitingQueue[T comparable](name string, rateLimiter workqueue.TypedRateLimiter[T]) workqueue.TypedRateLimitingInterface[T] {
|
||||
@@ -944,6 +947,48 @@ func (c *Controller) Run(ctx context.Context) {
|
||||
klog.Info("Shutting down workers")
|
||||
}
|
||||
|
||||
+func (c *Controller) dbStatus() {
|
||||
+ const maxFailures = 5
|
||||
+
|
||||
+ done := make(chan error, 2)
|
||||
+ go func() {
|
||||
+ done <- c.OVNNbClient.Echo(context.Background())
|
||||
+ }()
|
||||
+ go func() {
|
||||
+ done <- c.OVNSbClient.Echo(context.Background())
|
||||
+ }()
|
||||
+
|
||||
+ resultsReceived := 0
|
||||
+ timeout := time.After(time.Duration(c.config.OvnTimeout) * time.Second)
|
||||
+
|
||||
+ for resultsReceived < 2 {
|
||||
+ select {
|
||||
+ case err := <-done:
|
||||
+ resultsReceived++
|
||||
+ if err != nil {
|
||||
+ c.dbFailureCount++
|
||||
+ klog.Errorf("OVN database echo failed (%d/%d): %v", c.dbFailureCount, maxFailures, err)
|
||||
+ if c.dbFailureCount >= maxFailures {
|
||||
+ util.LogFatalAndExit(err, "OVN database connection failed after %d attempts", maxFailures)
|
||||
+ }
|
||||
+ return
|
||||
+ }
|
||||
+ case <-timeout:
|
||||
+ c.dbFailureCount++
|
||||
+ klog.Errorf("OVN database echo timeout (%d/%d) after %ds", c.dbFailureCount, maxFailures, c.config.OvnTimeout)
|
||||
+ if c.dbFailureCount >= maxFailures {
|
||||
+ util.LogFatalAndExit(nil, "OVN database connection timeout after %d attempts", maxFailures)
|
||||
+ }
|
||||
+ return
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if c.dbFailureCount > 0 {
|
||||
+ klog.Infof("OVN database connection recovered after %d failures", c.dbFailureCount)
|
||||
+ c.dbFailureCount = 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func (c *Controller) shutdown() {
|
||||
utilruntime.HandleCrash()
|
||||
|
||||
@@ -1277,6 +1322,8 @@ func (c *Controller) startWorkers(ctx context.Context) {
|
||||
if c.config.EnableLiveMigrationOptimize {
|
||||
go wait.Until(runWorker("add/update vmiMigration ", c.addOrUpdateVMIMigrationQueue, c.handleAddOrUpdateVMIMigration), 50*time.Millisecond, ctx.Done())
|
||||
}
|
||||
+
|
||||
+ go wait.Until(c.dbStatus, 15*time.Second, ctx.Done())
|
||||
}
|
||||
|
||||
func (c *Controller) allSubnetReady(subnets ...string) (bool, error) {
|
||||
diff --git a/pkg/ovs/interface.go b/pkg/ovs/interface.go
|
||||
index df6907c4d..5e70dd6c7 100644
|
||||
--- a/pkg/ovs/interface.go
|
||||
+++ b/pkg/ovs/interface.go
|
||||
@@ -1,6 +1,8 @@
|
||||
package ovs
|
||||
|
||||
import (
|
||||
+ "context"
|
||||
+
|
||||
netv1 "k8s.io/api/networking/v1"
|
||||
|
||||
"github.com/ovn-org/libovsdb/ovsdb"
|
||||
@@ -235,6 +237,7 @@ type SbClient interface {
|
||||
}
|
||||
|
||||
type Common interface {
|
||||
+ Echo(context.Context) error
|
||||
Transact(method string, operations []ovsdb.Operation) error
|
||||
GetEntityInfo(entity interface{}) error
|
||||
}
|
||||
109
packages/system/kubeovn/images/kubeovn/patches/northd_probe.diff
Normal file
109
packages/system/kubeovn/images/kubeovn/patches/northd_probe.diff
Normal file
@@ -0,0 +1,109 @@
|
||||
diff --git a/pkg/ovn_leader_checker/ovn.go b/pkg/ovn_leader_checker/ovn.go
|
||||
index 0f86a371d..8ddf7bca6 100755
|
||||
--- a/pkg/ovn_leader_checker/ovn.go
|
||||
+++ b/pkg/ovn_leader_checker/ovn.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
+ "sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -271,19 +272,56 @@ func checkNorthdSvcExist(cfg *Configuration, namespace, svcName string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
-func checkNorthdEpAvailable(ip string) bool {
|
||||
- address := net.JoinHostPort(ip, OvnNorthdPort)
|
||||
- conn, err := net.DialTimeout("tcp", address, 3*time.Second)
|
||||
- if err != nil {
|
||||
- klog.Errorf("failed to connect to northd leader %s, err: %v", ip, err)
|
||||
- failCount++
|
||||
- if failCount >= MaxFailCount {
|
||||
- return false
|
||||
- }
|
||||
- } else {
|
||||
+func checkNorthdEpAvailable(ips ...string) bool {
|
||||
+ var wg sync.WaitGroup
|
||||
+ success := make(chan struct{}, 1)
|
||||
+ failure := make(chan struct{})
|
||||
+ ctx, cancel := context.WithCancel(context.Background())
|
||||
+ defer cancel()
|
||||
+ d := net.Dialer{Timeout: 3 * time.Second}
|
||||
+ for _, ip := range ips {
|
||||
+ address := net.JoinHostPort(ip, OvnNorthdPort)
|
||||
+ wg.Add(1)
|
||||
+ go func() {
|
||||
+ defer wg.Done()
|
||||
+ conn, err := d.DialContext(ctx, "tcp", address)
|
||||
+ if err != nil {
|
||||
+ klog.Errorf("failed to connect to northd leader %s, err: %v", ip, err)
|
||||
+ return
|
||||
+ } else {
|
||||
+ defer conn.Close()
|
||||
+ select {
|
||||
+ case success <- struct{}{}:
|
||||
+ klog.V(5).Infof("succeed to connect to northd leader %s", ip)
|
||||
+ cancel()
|
||||
+ default:
|
||||
+ // someone else already succeeded
|
||||
+ }
|
||||
+ }
|
||||
+ }()
|
||||
+ }
|
||||
+ go func() {
|
||||
+ wg.Wait()
|
||||
+ close(failure)
|
||||
+ }()
|
||||
+ select {
|
||||
+ case <-success:
|
||||
failCount = 0
|
||||
- klog.V(5).Infof("succeed to connect to northd leader %s", ip)
|
||||
- _ = conn.Close()
|
||||
+ return true
|
||||
+ case <-failure:
|
||||
+ // if the last groroutine is the one to succeed,
|
||||
+ // there's a small chance that failure is selected,
|
||||
+ // this is a guard for this
|
||||
+ select {
|
||||
+ case <-success:
|
||||
+ failCount = 0
|
||||
+ return true
|
||||
+ default:
|
||||
+ failCount++
|
||||
+ if failCount >= MaxFailCount {
|
||||
+ return false
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -295,6 +333,8 @@ func checkNorthdEpAlive(cfg *Configuration, namespace, service string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
+ addresses := []string{}
|
||||
+
|
||||
for _, eps := range epsList.Items {
|
||||
for _, ep := range eps.Endpoints {
|
||||
if (ep.Conditions.Ready != nil && !*ep.Conditions.Ready) || len(ep.Addresses) == 0 {
|
||||
@@ -303,12 +343,15 @@ func checkNorthdEpAlive(cfg *Configuration, namespace, service string) bool {
|
||||
|
||||
// Found an address, check its availability. We only need one.
|
||||
klog.V(5).Infof("found address %s in endpoint slice %s/%s for service %s, checking availability", ep.Addresses[0], eps.Namespace, eps.Name, service)
|
||||
- return checkNorthdEpAvailable(ep.Addresses[0])
|
||||
+ addresses = append(addresses, ep.Addresses[0]) // Addresses are fungible by k8s API design
|
||||
}
|
||||
}
|
||||
|
||||
- klog.V(5).Infof("no address found in any endpoint slices for service %s/%s", namespace, service)
|
||||
- return false
|
||||
+ if len(addresses) == 0 {
|
||||
+ klog.V(5).Infof("no address found in any endpoint slices for service %s/%s", namespace, service)
|
||||
+ return false
|
||||
+ }
|
||||
+ return checkNorthdEpAvailable(addresses...)
|
||||
}
|
||||
|
||||
func compactOvnDatabase(db string) {
|
||||
Reference in New Issue
Block a user