Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-1.0]: Fix several issues for supporting DPUs #4761

Open
wants to merge 13 commits into
base: release-1.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions dist/images/Dockerfile.ubuntu.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# The standard name for this image is ovn-kube-ubuntu

# Notes:
# This is for a development build where the ovn-kubernetes utilities
# are built in this Dockerfile and included in the image (instead of the deb package)
#
#
# So this file will change over time.

FROM ubuntu:24.10

USER root

RUN apt-get update && apt-get install -y iproute2 curl software-properties-common util-linux

RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

# Install OVS and OVN packages.
RUN apt-get update && apt-get install -y openvswitch-switch openvswitch-common ovn-central ovn-common ovn-host

RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl" \
&& install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

RUN mkdir -p /var/run/openvswitch

# Built in ../../go_controller, then the binaries are copied here.
# put things where they are in the pkg
RUN mkdir -p /usr/libexec/cni/
COPY ovnkube ovn-kube-util ovndbchecker hybrid-overlay-node ovnkube-identity /usr/bin/
COPY ovn-k8s-cni-overlay /usr/libexec/cni/ovn-k8s-cni-overlay

# ovnkube.sh is the entry point. This script examines environment
# variables to direct operation and configure ovn
COPY ovnkube.sh /root/
COPY ovndb-raft-functions.sh /root/
# override the pkg's ovn_k8s.conf with this local copy
COPY ovn_k8s.conf /etc/openvswitch/ovn_k8s.conf

# copy git commit number into image
COPY git_info /root

# iptables wrappers
COPY ./iptables-scripts/iptables /usr/sbin/
COPY ./iptables-scripts/iptables-save /usr/sbin/
COPY ./iptables-scripts/iptables-restore /usr/sbin/
COPY ./iptables-scripts/ip6tables /usr/sbin/
COPY ./iptables-scripts/ip6tables-save /usr/sbin/
COPY ./iptables-scripts/ip6tables-restore /usr/sbin/

LABEL io.k8s.display-name="ovn-kubernetes" \
io.k8s.description="ovnkube ubuntu image"

WORKDIR /root
ENTRYPOINT /root/ovnkube.sh
16 changes: 16 additions & 0 deletions dist/images/daemonset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ OVN_ENABLE_INTERCONNECT=
OVN_ENABLE_OVNKUBE_IDENTITY="true"
OVN_ENABLE_PERSISTENT_IPS=
OVN_ENABLE_SVC_TEMPLATE_SUPPORT="true"
OVN_NOHOSTSUBNET_LABEL=""
OVN_DISABLE_REQUESTEDCHASSIS="false"
# IN_UPGRADE is true only if called by upgrade-ovn.sh during the upgrade test,
# it will render only the parts in ovn-setup.yaml related to RBAC permissions.
IN_UPGRADE=
Expand Down Expand Up @@ -346,6 +348,12 @@ while [ "$1" != "" ]; do
--enable-svc-template-support)
OVN_ENABLE_SVC_TEMPLATE_SUPPORT=$VALUE
;;
--no-hostsubnet-label)
OVN_NOHOSTSUBNET_LABEL=$VALUE
;;
--ovn_disable_requestedchassis)
OVN_DISABLE_REQUESTEDCHASSIS=$value
;;
*)
echo "WARNING: unknown parameter \"$PARAM\""
exit 1
Expand Down Expand Up @@ -531,6 +539,12 @@ echo "ovn_enable_persistent_ips: ${ovn_enable_persistent_ips}"
ovn_enable_svc_template_support=${OVN_ENABLE_SVC_TEMPLATE_SUPPORT}
echo "ovn_enable_svc_template_support: ${ovn_enable_svc_template_support}"

ovn_nohostsubnet_label=${OVN_NOHOSTSUBNET_LABEL}
echo "ovn_nohostsubnet_label: ${ovn_nohostsubnet_label}"

ovn_disable_requestedchassis=${OVN_DISABLE_REQUESTEDCHASSIS}
echo "ovn_disable_requestedchassis: ${ovn_disable_requestedchassis}"

ovn_image=${ovnkube_image} \
ovnkube_compact_mode_enable=${ovnkube_compact_mode_enable} \
ovn_image_pull_policy=${image_pull_policy} \
Expand Down Expand Up @@ -716,6 +730,8 @@ ovn_image=${ovnkube_image} \
ovn_enable_ovnkube_identity=${ovn_enable_ovnkube_identity} \
ovn_enable_persistent_ips=${ovn_enable_persistent_ips} \
ovn_enable_svc_template_support=${ovn_enable_svc_template_support} \
ovn_nohostsubnet_label=${ovn_nohostsubnet_label} \
ovn_disable_requestedchassis=${ovn_disable_requestedchassis} \
jinjanate ../templates/ovnkube-master.yaml.j2 -o ${output_dir}/ovnkube-master.yaml

ovn_image=${ovnkube_image} \
Expand Down
51 changes: 51 additions & 0 deletions dist/images/ovnkube.sh
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,11 @@ ovnkube_compact_mode_enable=${OVNKUBE_COMPACT_MODE_ENABLE:-false}
ovn_northd_backoff_interval=${OVN_NORTHD_BACKOFF_INTERVAL:-"300"}
# OVN_ENABLE_SVC_TEMPLATE_SUPPORT - enable svc template support
ovn_enable_svc_template_support=${OVN_ENABLE_SVC_TEMPLATE_SUPPORT:-true}
# OVN_NOHOSTSUBNET_LABEL - node label indicating nodes managing their own network
ovn_nohostsubnet_label=${OVN_NOHOSTSUBNET_LABEL:-""}
# OVN_DISABLE_REQUESTEDCHASSIS - disable requested-chassis option during pod creation
# should be set to true when dpu nodes are in the cluster
ovn_disable_requestedchassis=${OVN_DISABLE_REQUESTEDCHASSIS:-false}

# Determine the ovn rundir.
if [[ -f /usr/bin/ovn-appctl ]]; then
Expand Down Expand Up @@ -1247,6 +1252,17 @@ ovn-master() {
ovn_enable_svc_template_support_flag="--enable-svc-template-support"
fi
echo "ovn_enable_svc_template_support_flag=${ovn_enable_svc_template_support_flag}"

nohostsubnet_label_option=
if [[ ${ovn_nohostsubnet_label} != "" ]]; then
nohostsubnet_label_option="--no-hostsubnet-nodes=${ovn_nohostsubnet_label}"
fi

ovn_disable_requestedchassis_flag=
if [[ ${ovn_disable_requestedchassis} == "true" ]]; then
ovn_disable_requestedchassis_flag="--disable-requestedchassis"
fi
echo "ovn_disable_requestedchassis_flag=${ovn_disable_requestedchassis_flag}"

init_node_flags=
if [[ ${ovnkube_compact_mode_enable} == "true" ]]; then
Expand Down Expand Up @@ -1291,6 +1307,8 @@ ovn-master() {
${ovn_v6_join_subnet_opt} \
${ovn_v6_masquerade_subnet_opt} \
${persistent_ips_enabled_flag} \
${nohostsubnet_label_option} \
${ovn_disable_requestedchassis_flag} \
--cluster-subnets ${net_cidr} --k8s-service-cidr=${svc_cidr} \
--gateway-mode=${ovn_gateway_mode} ${ovn_gateway_opts} \
--host-network-namespace ${ovn_host_network_namespace} \
Expand Down Expand Up @@ -2393,6 +2411,39 @@ ovn-node() {
node_mgmt_port_netdev_flags="$node_mgmt_port_netdev_flags --ovnkube-node-mgmt-port-dp-resource-name ${ovnkube_node_mgmt_port_dp_resource_name}"
fi

if [[ ${ovnkube_node_mode} == "dpu" ]]; then
# in the case of dpu mode we want the host K8s Node Name and not the DPU K8s Node Name
K8S_NODE=$(ovs-vsctl --if-exists get Open_vSwitch . external_ids:host-k8s-nodename | tr -d '\"')
if [[ ${K8S_NODE} == "" ]]; then
echo "Couldn't get the required Host K8s Nodename. Exiting..."
exit 1
fi
if [[ ${ovn_gateway_opts} == "" ]]; then
# get the gateway interface
gw_iface=$(ovs-vsctl --if-exists get Open_vSwitch . external_ids:ovn-gw-interface | tr -d \")
if [[ ${gw_iface} == "" ]]; then
echo "Couldn't get the required OVN Gateway Interface. Exiting..."
exit 1
fi
ovn_gateway_opts="--gateway-interface=${gw_iface} "

# get the gateway nexthop
gw_nexthop=$(ovs-vsctl --if-exists get Open_vSwitch . external_ids:ovn-gw-nexthop | tr -d \")
if [[ ${gw_nexthop} == "" ]]; then
echo "Couldn't get the required OVN Gateway NextHop. Exiting..."
exit 1
fi
ovn_gateway_opts+="--gateway-nexthop=${gw_nexthop} "
fi

# this is required if the DPU and DPU Host are in different subnets
if [[ ${ovn_gateway_router_subnet} == "" ]]; then
# get the gateway router subnet
ovn_gateway_router_subnet=$(ovs-vsctl --if-exists get Open_vSwitch . external_ids:ovn-gw-router-subnet | tr -d \")
fi

fi

local ovn_node_ssl_opts=""
if [[ ${ovnkube_node_mode} != "dpu-host" ]]; then
[[ "yes" == ${OVN_SSL_ENABLE} ]] && {
Expand Down
4 changes: 4 additions & 0 deletions dist/templates/ovnkube-master.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ spec:
value: "{{ ovn_enable_multi_external_gateway }}"
- name: OVN_ENABLE_SVC_TEMPLATE_SUPPORT
value: "{{ ovn_enable_svc_template_support }}"
- name: OVN_NOHOSTSUBNET_LABEL
value: "{{ ovn_nohostsubnet_label }}"
- name: OVN_DISABLE_REQUESTEDCHASSIS
value: "{{ ovn_disable_requestedchassis }}"
- name: OVN_HOST_NETWORK_NAMESPACE
valueFrom:
configMapKeyRef:
Expand Down
20 changes: 19 additions & 1 deletion dist/templates/ovnkube-node.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ spec:
name: ovn-config
key: routable_mtu
optional: true
{%-if ovnkube_app_name=="ovnkube-node-dpu" %}
- name: K8S_NODE_DPU
{%- else %}
- name: K8S_NODE
{%- endif %}
valueFrom:
fieldRef:
fieldPath: spec.nodeName
Expand Down Expand Up @@ -255,13 +259,23 @@ spec:
fieldPath: metadata.name

readinessProbe:
{%- if ovnkube_app_name!="ovnkube-node-dpu" %}
exec:
command: ["/usr/bin/ovn-kube-util", "readiness-probe", "-t", "ovnkube-node"]
initialDelaySeconds: 30
timeoutSeconds: 30
periodSeconds: 60
{%- else %}
httpGet:
path: /metrics
port: 9476
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 30
{%- endif %}
{% endif %}
{% if ovnkube_app_name=="ovnkube-node" -%}
{% if ovnkube_app_name!="ovnkube-node-dpu-host" -%}
- name: ovn-controller
image: "{{ ovn_image | default('docker.io/ovnkube/ovn-daemonset:latest') }}"
imagePullPolicy: "{{ ovn_image_pull_policy | default('IfNotPresent') }}"
Expand Down Expand Up @@ -304,7 +318,11 @@ spec:
configMapKeyRef:
name: ovn-config
key: k8s_apiserver
{%- if ovnkube_app_name=="ovnkube-node-dpu" %}
- name: K8S_NODE_DPU
{%- else %}
- name: K8S_NODE
{%- endif %}
valueFrom:
fieldRef:
fieldPath: spec.nodeName
Expand Down
9 changes: 8 additions & 1 deletion go-controller/cmd/ovnkube/ovnkube.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,14 @@ func startOvnKube(ctx *cli.Context, cancel context.CancelFunc) error {
}()

if config.Kubernetes.BootstrapKubeconfig != "" {
if err := util.StartNodeCertificateManager(ctx.Context, ovnKubeStartWg, os.Getenv("K8S_NODE"), &config.Kubernetes); err != nil {
// In the case of dpus K8S_NODE will be set to dpu host's name
var csrNodeName string
if config.OvnKubeNode.Mode == types.NodeModeDPU {
csrNodeName = os.Getenv("K8S_NODE_DPU")
} else {
csrNodeName = os.Getenv("K8S_NODE")
}
if err := util.StartNodeCertificateManager(ctx.Context, ovnKubeStartWg, csrNodeName, &config.Kubernetes); err != nil {
return fmt.Errorf("failed to start the node certificate manager: %w", err)
}
}
Expand Down
63 changes: 36 additions & 27 deletions go-controller/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,14 @@ var (

// Kubernetes holds Kubernetes-related parsed config file parameters and command-line overrides
Kubernetes = KubernetesConfig{
APIServer: DefaultAPIServer,
RawServiceCIDRs: "172.16.1.0/24",
OVNConfigNamespace: "ovn-kubernetes",
HostNetworkNamespace: "",
PlatformType: "",
DNSServiceNamespace: "kube-system",
DNSServiceName: "kube-dns",
APIServer: DefaultAPIServer,
RawServiceCIDRs: "172.16.1.0/24",
OVNConfigNamespace: "ovn-kubernetes",
HostNetworkNamespace: "",
DisableRequestedChassis: false,
PlatformType: "",
DNSServiceNamespace: "kube-system",
DNSServiceName: "kube-dns",
// By default, use a short lifetime length for certificates to ensure that the automatic rotation works well,
// might revisit in the future to use a more sensible value
CertDuration: 10 * time.Minute,
Expand Down Expand Up @@ -340,26 +341,27 @@ type CNIConfig struct {

// KubernetesConfig holds Kubernetes-related parsed config file parameters and command-line overrides
type KubernetesConfig struct {
BootstrapKubeconfig string `gcfg:"bootstrap-kubeconfig"`
CertDir string `gcfg:"cert-dir"`
CertDuration time.Duration `gcfg:"cert-duration"`
Kubeconfig string `gcfg:"kubeconfig"`
CACert string `gcfg:"cacert"`
CAData []byte
APIServer string `gcfg:"apiserver"`
Token string `gcfg:"token"`
TokenFile string `gcfg:"tokenFile"`
CompatServiceCIDR string `gcfg:"service-cidr"`
RawServiceCIDRs string `gcfg:"service-cidrs"`
ServiceCIDRs []*net.IPNet
OVNConfigNamespace string `gcfg:"ovn-config-namespace"`
OVNEmptyLbEvents bool `gcfg:"ovn-empty-lb-events"`
PodIP string `gcfg:"pod-ip"` // UNUSED
RawNoHostSubnetNodes string `gcfg:"no-hostsubnet-nodes"`
NoHostSubnetNodes labels.Selector
HostNetworkNamespace string `gcfg:"host-network-namespace"`
PlatformType string `gcfg:"platform-type"`
HealthzBindAddress string `gcfg:"healthz-bind-address"`
BootstrapKubeconfig string `gcfg:"bootstrap-kubeconfig"`
CertDir string `gcfg:"cert-dir"`
CertDuration time.Duration `gcfg:"cert-duration"`
Kubeconfig string `gcfg:"kubeconfig"`
CACert string `gcfg:"cacert"`
CAData []byte
APIServer string `gcfg:"apiserver"`
Token string `gcfg:"token"`
TokenFile string `gcfg:"tokenFile"`
CompatServiceCIDR string `gcfg:"service-cidr"`
RawServiceCIDRs string `gcfg:"service-cidrs"`
ServiceCIDRs []*net.IPNet
OVNConfigNamespace string `gcfg:"ovn-config-namespace"`
OVNEmptyLbEvents bool `gcfg:"ovn-empty-lb-events"`
PodIP string `gcfg:"pod-ip"` // UNUSED
RawNoHostSubnetNodes string `gcfg:"no-hostsubnet-nodes"`
NoHostSubnetNodes labels.Selector
HostNetworkNamespace string `gcfg:"host-network-namespace"`
DisableRequestedChassis bool `gcfg:"disable-requestedchassis"`
PlatformType string `gcfg:"platform-type"`
HealthzBindAddress string `gcfg:"healthz-bind-address"`

// CompatMetricsBindAddress is overridden by the corresponding option in MetricsConfig
CompatMetricsBindAddress string `gcfg:"metrics-bind-address"`
Expand Down Expand Up @@ -628,6 +630,7 @@ func PrepareTestConfig() error {
HybridOverlay = savedHybridOverlay
OvnKubeNode = savedOvnKubeNode
ClusterManager = savedClusterManager
Kubernetes.DisableRequestedChassis = false
EnableMulticast = false

if err := completeConfig(); err != nil {
Expand Down Expand Up @@ -1156,6 +1159,12 @@ var K8sFlags = []cli.Flag{
Destination: &cliConfig.Kubernetes.HostNetworkNamespace,
Value: Kubernetes.HostNetworkNamespace,
},
&cli.BoolFlag{
Name: "disable-requestedchassis",
Usage: "If set to true, requested-chassis option will not be set during pod creation",
Destination: &cliConfig.Kubernetes.DisableRequestedChassis,
Value: Kubernetes.DisableRequestedChassis,
},
&cli.StringFlag{
Name: "platform-type",
Usage: "The cloud provider platform type ovn-kubernetes is deployed on. " +
Expand Down
3 changes: 3 additions & 0 deletions go-controller/pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ no-hostsubnet-nodes=label=another-test-label
healthz-bind-address=0.0.0.0:1234
dns-service-namespace=kube-system-f
dns-service-name=kube-dns-f
disable-requestedchassis=false

[metrics]
bind-address=1.1.1.1:8080
Expand Down Expand Up @@ -739,6 +740,7 @@ var _ = Describe("Config Operations", func() {
gomega.Expect(Kubernetes.HealthzBindAddress).To(gomega.Equal("0.0.0.0:4321"))
gomega.Expect(Kubernetes.DNSServiceNamespace).To(gomega.Equal("kube-system-2"))
gomega.Expect(Kubernetes.DNSServiceName).To(gomega.Equal("kube-dns-2"))
gomega.Expect(Kubernetes.DisableRequestedChassis).To(gomega.BeTrue())
gomega.Expect(Default.ClusterSubnets).To(gomega.Equal([]CIDRNetworkEntry{
{ovntest.MustParseIPNet("10.130.0.0/15"), 24},
}))
Expand Down Expand Up @@ -863,6 +865,7 @@ var _ = Describe("Config Operations", func() {
"-zone=bar",
"-dns-service-namespace=kube-system-2",
"-dns-service-name=kube-dns-2",
"-disable-requestedchassis=true",
"-cluster-manager-v4-transit-switch-subnet=100.90.0.0/16",
"-cluster-manager-v6-transit-switch-subnet=fd96::/64",
}
Expand Down
Loading
Loading