Skip to content

[pull] master from kubernetes:master - #1924

Open
pull[bot] wants to merge 8709 commits into
next-stack:masterfrom
kubernetes:master
Open

[pull] master from kubernetes:master#1924
pull[bot] wants to merge 8709 commits into
next-stack:masterfrom
kubernetes:master

Conversation

@pull

@pull pull Bot commented Oct 24, 2021

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull Bot added the ⤵️ pull label Oct 24, 2021
Ciprian Hacman and others added 29 commits July 30, 2026 19:31
Update the gossip docs for the removal that shipped in kOps 1.37, with
the deprecation and removal timeline, the changes shipped in kOps 1.36,
and a step-by-step guide for migrating existing gossip clusters to
None-DNS using kOps 1.36 before upgrading. Note that nodes no longer
install or run protokube, and that the gossipConfig and
dnsControllerGossipConfig cluster spec fields are deprecated, have no
effect, and are rejected by validation when set.

Align the 1.36 release notes with the removal plan from #18240, use
None-DNS wording in the docs that still described clusters as created
without DNS, and remove the outdated AWS China guide, which documented
kOps 1.10 procedures and is superseded by the None-DNS support in the
getting started guide.
chore(networking): bump aws-cni to version 1.22.4
pkg/dns/hosts (the /etc/hosts writer used by none-DNS clusters) and
pkg/etcd (etcd cluster spec parsing from volume tags) are still used
outside protokube, so relocate them ahead of the protokube removal.
protokube temporarily imports the new locations.
protokube no longer had any responsibilities after the gossip DNS
removal: nodes stopped installing and running it, and its only remaining
function was serving gossip DNS. Delete the protokube tree, the forked
memberlistmesh library, and the gcediscovery package whose only consumer
was protokube's GCE volume provider. Remove the protokube build targets
and stop publishing its release assets.

The gossip well-known ports are kept (and the two dns-controller ones
restored) as Deprecated constants so the port numbers are not reused.

The release promotion and validation scripts learn an OPTIONAL_BINARIES
mechanism, probing artifacts.k8s.io per version, so older releases that
still ship protokube (and channels, dropped in kOps 1.36) keep full
coverage while newer releases skip them. Only a confirmed 404 counts as
absent; any other probe outcome fails the scripts.
github.com/hashicorp/memberlist and github.com/weaveworks/mesh are no
longer used after the protokube removal.
Removed concept of CCM node as it is dynamic.
Fixed KubController -> KubeController.
Added setting kops role labels on nodes via kops-channel.
Fixed APIServer label test.
Fix IG HasAPIServer to RunsAPIServer
docs: gossip removal in kOps 1.37 and migration guide
The DIGITALOCEAN_ACCESS_TOKEN, HCLOUD_TOKEN and SCW_* exports in the
bootstrap script existed only for protokube's gossip seed discovery.
Workers stopped receiving them in kOps 1.36 and protokube itself was
removed in kOps 1.37, so the control-plane exports and their
persistence in /etc/sysconfig/kops-configuration have no consumer
left. All remaining consumers (etcd-manager, kops-controller,
dns-controller, CCM, CSI) receive credentials via manifests built at
kops update time.

Also write /etc/sysconfig/kops-configuration with mode 0600; it can
still contain state store and OpenStack credentials and was
previously world-readable.
…URST

Signed-off-by: ronaldngounou <rngounou@amazon.com>
…odeSyncs

Signed-off-by: ronaldngounou <rngounou@amazon.com>
Skip the dns-controller Route 53 grant on the control-plane instance
role when useServiceAccountExternalPermissions is set; dns-controller
and external-dns get dedicated IAM roles in that mode, matching how
the other addon permissions are handled.

Scope the kube-router and kindnet ec2:ModifyInstanceAttribute grants
to cluster-tagged instances, matching the CCM and IRSA variants of
the same permission. Add golden coverage for the kube-router node
policy.
Narrow instance cloud permissions to actual consumers
The list of expected files in Go was a second copy of the test data
directory, which now also has to describe conditional output: an
instance role that needs no permissions has no inline IAM policy.

Nothing is lost by dropping it. hack/update-expected.sh never deletes
existing expected files, so a file that is wrongly no longer generated
keeps failing the comparison until its expected file is deleted too.
Grant ec2:DescribeInstanceTypes only where something on the instance
calls it: nodeup Nvidia GPU detection and the kubelet MaxPods
calculation for AWS VPC CNI and Cilium ENI IPAM. The cluster
autoscaler grant now honors awsUseStaticInstanceList, whose branch was
a no-op because the action was also inserted unconditionally.

Drop ec2:DescribeRegions from the etcd-manager permissions, as it
reads the region from the instance metadata service. Move
ec2:DescribeInstances to a kops-controller helper, which needs it for
node verification and identification independently of etcd-manager.

Render policies without statements as empty documents instead of
erroring, so that roles which need no permissions, such as the bastion
role, have no inline policy. Updating an existing cluster deletes the
policy created for it before.
isHealthy() marked an object unhealthy on any status condition with a
"False" status, regardless of the condition type. Controllers routinely
publish conditions that carry no readiness meaning: KEDA sets "Paused" to
"False" on every ScaledObject and ScaledJob it is actively scaling, and a
healthy Node reports "MemoryPressure", "DiskPressure" and "PIDPressure" as
"False". Such objects were permanently unhealthy, so an addon containing
one could never be applied successfully.

Since kops 1.36 the kops-channels pod reports readiness from the result of
the last apply iteration, so this also leaves the pod permanently not ready
and cluster validation failing.

Only consider condition types whose "True" status means the object is
healthy, and ignore the rest. Abnormal-true conditions are deliberately not
interpreted, matching the previous behaviour for those.

Signed-off-by: Joakim Olsson <joakim@unbound.se>
Ciprian Hacman and others added 30 commits August 26, 2026 18:21
The KopsConfig reconciler and the node config server both failed when
the cluster channel could not be read, e.g. a file:// channel set by
the e2e harness that only exists on the machine that created the
cluster. The channel only provides optional defaults here, so warn and
continue like apply_cluster does.

With a nil channel, instance group spec population then fails resolving
a default machine image on GCE. The image is chosen by the CAPI
infrastructure provider and is not used for nodeup config generation,
so give the placeholder instance groups a placeholder image.
kube-proxy special-cased only control-plane nodes for the localhost
address and used the API internal name on dedicated apiserver nodes.
Those nodes have no /etc/hosts record for that name (and no DNS record
in dns=none clusters, previously masked by gossip), so kube-proxy could
never reach the API and never programmed cluster IPs. As a result the
local kube-apiserver could not call any admission webhook by service,
failing with a timeout regardless of where the webhook pods run.

Use the same HasAPIServer condition as the kubeconfig builders.
Firewall source tags only match traffic sent from an instance's primary
address, so pod-sourced traffic is matched by CIDR instead. That rule
only targeted node instances, leaving pods unable to reach pods hosted
on control plane or dedicated apiserver nodes, such as addons that are
pinned to the control plane. Grant pod CIDRs the same limited port set
that nodes get, so host ports such as etcd stay protected.
keypair-ids.yaml covers every keypair on the host, while the server
keystore only loads the CAs it is configured to serve, so the etcd CAs
always trigger this warning on the CAPI node bootstrap path.
The clusterapi, splitkcp and ai-conformance scenarios each installed
cert-manager from their own pinned upstream release URL, with two
different versions across the three scripts. Enable the bundled
certmanager.io addon in the cluster spec instead, so the tree has a
single cert-manager definition and version bumps happen only in the
addon.

The explicit readiness waits are no longer needed: the addon runs its
pods with the system-cluster-critical priority class, and cluster
validation during kops-up fails while any such pod is pending or not
ready.
test(e2e): deploy cert-manager via the certmanager.io addon
No Prow job runs this script. All eight DigitalOcean jobs invoke
"make test-e2e-install" and kubetest2 directly from their job config, and the
JOB_NAME it hardcodes, pull-kops-e2e-kubernetes-do-kubetest2, no longer exists
anywhere in test-infra. The e2e-do-kubetest2 testgrid tab it was named for now
belongs to pull-kops-e2e-kubernetes-do-fqdn, which does not use the script.

It could not work if it were run. It pins Kubernetes 1.27 via
stable-1.27.txt, well below OldestSupportedKubernetesVersion, and it calls
"go get sigs.k8s.io/kubetest2/...@latest" from the repo root, which on
supported Go versions edits go.mod instead of installing anything.

Last touched in 2023.
Now that the e2e scenarios enable the certmanager.io addon rather than applying
an upstream manifest, this echo is the last place in the tree naming a
cert-manager version, and it named an older one than the addon deploys.

Point it at the addon's version.
Remove the orphaned digital-ocean e2e scenario
Remove unused hack scripts and a duplicate hash generator line
Every YAML example under docs/ was strict-decoded through the kOps API
scheme, and every documented kops command was checked against the 1.37
flag set.

Fix examples that current kOps would reject:

* networking.kubeRouter and calico.IPIPMode do not match the JSON tags
  in the API types; they are kuberouter and ipipMode
* clusterAutoscaler.scaleDownUtilizationThreshold and a kubeAPIServer
  env value were unquoted numbers, but both fields are strings
* an InstanceGroup in the Spot Ocean docs had its spec nested under
  metadata
* iam_roles used the long-removed zones field instead of subnets
* the GPU taint was shown as a Kubernetes taint object, but the kOps
  taints field takes strings
* a missing line continuation split the GCE create cluster command

Rename the flags that moved to control-plane naming (--master-zones,
--master-size, --master-count, --master-volume-size, --master-interval)
and --vpc, which is now --network-id. kops toolbox instance-selector
takes the instance group name as a positional argument.

Drop the containerRuntime and spec.docker sections, as validation now
rejects containerRuntime: docker outright.

Refresh stale versions and images: Kubernetes 1.36.4, containerd 2.3.4,
and Ubuntu 24.04 in place of focal, CoreOS, kope.io and debian-9
references. The exported manifest in manifests_and_customizing_via_api
was regenerated with kops create cluster --dry-run -o yaml.

Remove the Ubuntu 20.04 and Debian 10 sections from the images doc.
Both distros were removed in kOps 1.36 and were the only removed
distros still listed under Supported Distros.

Examples stay on the v1alpha2 apiVersion, which is what kOps writes.
docs: refresh CLI examples and manifests for kOps 1.37
A v1alpha2 spec whose spec.kubeAPIServer.oidcRequiredClaim held an entry
without an "=" crashed the conversion with an index out of range, because
strings.SplitN was indexed unconditionally. Return a field.Invalid naming
the offending index instead.

Build the OIDC settings before publishing them, too. The generated
conversion copies the OIDC pointer straight across, so writing into
out.Authentication.OIDC could mutate the caller's object, and returning
the new error partway through would leave it half rewritten.
TestRoundTripTypes excluded Cluster, ClusterList, InstanceGroup and
InstanceGroupList for both versions, so it only covered Host, Keyset and
SSHCredential: none of which have hand-written conversions. Every field
that v1alpha2 renames, flattens or inverts went untested, and there is no
codegen signal to fall back on because v1alpha2 has no AWSSpec or GCESpec
types at all, so a field added to either gets no warning.

Fuzz each version with its own functions, since the two lose different
fields. What those functions clear is the catalogue of what is silently
dropped on write. Discover kinds from the scheme so a new type is covered
without being listed, and fail if a new API version arrives without fuzzer
functions describing what it loses.

Add unit tests pinning the manual v1alpha2 conversions the fuzzer has to
exclude: the inverted booleans, the control-plane/master renaming, the
rootVolume flattening, the OIDC promotion including the cases the flag
encoding cannot represent, and the cloudProvider string.

sigs.k8s.io/randfill becomes a direct dependency; vendor is unchanged.
Ports the applicable pieces of upstream's daemonset modernization work.
Six changes, in rough order of how much they matter:

* Gate liveness behind a startup probe. We were giving kube-router
  initialDelaySeconds: 10 plus the default failureThreshold: 3 at
  periodSeconds: 3, so roughly 19 seconds before the kubelet kills it.
  But --cache-sync-timeout defaults to a full minute, so on a cluster
  large enough that informer sync runs long, kube-router
  CrashLoopBackOffs on startup and never comes up. The startup probe
  allows 150 seconds, and liveness only starts once it passes.

* Add type: File to the kubeconfig hostPath. Without it, a missing
  kubeconfig gets silently papered over by the kubelet creating a
  directory at that path. nodeup writes the file before kubelet.service
  on every node running kube-router, so this can't regress a healthy
  node, it just turns a confusing failure into a loud FailedMount.

* Update cniVersion 0.3.0 -> 1.0.0. Our oldest CNI plugin asset is
  containernetworking/plugins v1.3.0 (k8s 1.29), well past the v1.0.0
  that added spec 1.0.0 support, and portmap ships in the same release.
  Note that because the initContainer only writes the conflist when it's
  absent, this reaches newly-provisioned nodes only. Existing nodes keep
  0.3.0 until they're replaced, and since both versions work, the mixed
  state is harmless.

* Drop dead RBAC grants. Since the service proxy moved to
  EndpointSlices, the only surviving v1.Endpoints reference is
  isEndpointsForLeaderElection, and nothing calls it. The extensions API
  version was removed in k8s 1.16 and we support 1.29+.

* Drop the deprecated serviceAccount field, which came back in when the
  v2.10.0 bump re-pulled from upstream's older kubeadm manifest. It's
  the long-deprecated alias for serviceAccountName, both were set to the
  same value, and upstream has since removed it.

* Add dnsPolicy: Default and a linux nodeSelector. The dnsPolicy is
  effectively a no-op on a hostNetwork pod because the kubelet already
  coerces ClusterFirst to Default, but it records the reasoning. The
  nodeSelector matches what calico, cilium, coredns and metrics-server
  already do.

Also refreshes the source URL, which pointed at the v2.1.0 kubeadm
manifest even though what we ship much more closely resembles
generic-kuberouter-all-features.yaml.

We deliberately keep the kind: User / name: system:kube-router subject
on the ClusterRoleBinding. That's ours, not upstream's, since control
plane nodes get an issued client cert with that CN.
We already mount the containerd socket and pass
--runtime-endpoint=unix:///run/containerd/containerd.sock, which
kube-router only ever uses for DSR, but we never set hostIPC: true.
Upstream's DSR docs list that as mandatory, and their
kubeadm-kuberouter-all-features-dsr.yaml manifest sets all three of
hostNetwork, hostIPC and hostPID, so what we ship today is half-wired:
the plumbing is there but DSR can't actually work.

This does widen the pod's privileges, which is worth being explicit
about. In practice it's a small step from where we already are, because
the container runs privileged: true with hostNetwork and hostPID
already, and hostIPC is the last piece DSR needs in order to enter the
pod's network namespace through the runtime.
Since v2.8.0 kube-router defaults --strict-external-ip-validation to
true, and its filters default-deny: with no ranges configured,
FilterExternalIPs and FilterLoadBalancerIPs both return nothing, so
every externalIP and loadBalancerIP drops out of IPVS and stops being
advertised over BGP. We pin the flag off today to avoid breaking
existing clusters, but that leaves no way to turn the feature on at all.

Add externalIPRanges and loadBalancerIPRanges to
KuberouterNetworkingSpec and emit the matching
--service-external-ip-range and --loadbalancer-ip-range flags. Strict
validation now follows the config: setting either list turns it on,
leaving both empty keeps it off, so upgrades are unaffected and opting
in is a deliberate act.

There's no options builder for this because empty is semantically
meaningful here, it's precisely the signal for "keep strict validation
off", so there's nothing to default.

Validation moves out of the inline block in validateNetworking into
validateNetworkingKubeRouter, which lets us reuse the already-parsed
serviceClusterIPRange. Each CIDR has to parse, has to match the
cluster's IP family, and must not overlap the service cluster IP range.
That last one is worth failing early on because kube-router rejects
those at runtime anyway, so an overlap would otherwise turn into a
silently dead range rather than an error at kops update cluster time.
The family check is a predicate over the cluster's stack rather than a
blanket IPv6 rejection, so allowing IPv6-only clusters later widens it
instead of rewriting it.

Two side effects are documented but not otherwise handled:
--service-external-ip-range also feeds the network policy controller's
firewall rules, which was the flag's original purpose upstream, and
--loadbalancer-ip-range does not activate kube-router's load balancer
IPAM, which is gated separately on --run-loadbalancer.
Two teardown failures where a leaked resource keeps the network alive
until `kops delete cluster` gives up:

Routes were deleted once all the instances were gone, but not once the
managed instance groups were gone. A MIG whose deletion is still blocked
- typically the control-plane MIG, which GCE refuses to delete while the
api BackendService refers to its instance group - recreates a
control-plane instance, and its route controller recreates the routes we
just deleted. Block route deletion on the MIGs as well.

Firewall rules created for a Service of type LoadBalancer were only
matched for externalTrafficPolicy: Cluster. With Local, the health check
is named for the load balancer rather than k8s-<clusterid>-node, so we
abandoned the whole load balancer as "not a k8s rule", and its
k8s-<loadbalancer>-http-hc firewall matched neither that path nor the
-node-http-hc rule.

Also order the ForwardingRule -> BackendService -> {HealthCheck, MIG}
deletions that GCE enforces, so each one no longer costs a retry
interval.
…tion

kube-router Daemonset Modernization
fix: persist binariesLocation for AWS and GCE in v1alpha2
Round trip Cluster and InstanceGroup across API versions
aws: Generate NodePool requirements for instanceRequirements
…d-lb-firewalls

gce: don't leave routes and LB firewalls behind on cluster deletion
aws: validate Karpenter InstanceGroups early
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.