Closed mtb-xt closed 3 weeks ago
What implements the 172.21.35.10
keepalived virtual ip ? Where and how is it pointing to? How and what does it translate to when a client uses it?
the service IP, there is no 'backend'
If you list kubernetes
endpoints, what do you get?
Pods can't talk to the API server internally - dial tcp 10.96.0.1:443: connect: operation not permitted
Definitely the result of not having any backends.
What implements the
172.21.35.10
keepalived virtual ip ? Where and how is it pointing to? How and what does it translate to when a client uses it?
There is a keepalived daemon on each kubernetes controlplane node, one of the controlplanes gets the 172.21.35.10 IP. haproxy listens on all controlplanes on this ip, and then tcp forwards to one of the controllers.
that IP is used in k0s as the external IP address, I also use this address in my kubeconfig file (and it works).
The virtual IP points to one of the controlplane mac addresses:
hawara@phoenix:~$ arp -an
? (172.21.35.10) at 52:54:00:56:d5:06 [ether] on enp1s0
? (172.21.35.13) at 52:54:00:56:d5:06 [ether] on enp1s0
? (172.21.35.11) at 52:54:00:be:58:d0 [ether] on enp1s0
[hawara@phoenix ~]$ kubectl cluster-info
Kubernetes control plane is running at https://172.21.35.10:6443
CoreDNS is running at https://172.21.35.10:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
keepalived conf
root@sentinel-cp:/etc/keepalived# cat keepalived.conf
#
# Ansible managed
#
vrrp_instance VI_1 {
state MASTER
interface enp1s0
virtual_router_id 52
priority 255
authentication {
auth_type PASS
auth_pass <bogus>
}
virtual_ipaddress {
172.21.35.10/23
}
}
the service IP, there is no 'backend'
If you list
kubernetes
endpoints, what do you get?[hawara@phoenix ~]$ k get endpoints kubernetes NAME ENDPOINTS AGE kubernetes 172.21.35.10:6443 37d
[hawara@phoenix ~]$ k get endpointslices.discovery.k8s.io NAME ADDRESSTYPE PORTS ENDPOINTS AGE kubernetes IPv4 6443 172.21.35.10 37d
>
> > Pods can't talk to the API server internally - dial tcp 10.96.0.1:443: connect: operation not permitted
>
> Definitely the result of not having any backends.
Even if I try to manually specify each controlplane IP in `kubernetes` service endpoint, there are still no backends in bpf nat.
I've added debug logs to Felix, it seems it really skips the endpoints of the kubernetes service:
2023-10-25 04:43:10.974 [DEBUG][519655] felix/syncer.go 549: Applying service service=default/kubernetes:https
2023-10-25 04:43:10.974 [DEBUG][519655] felix/syncer.go 865: bpf map writing NATKey{Proto:6 Addr:10.96.0.1 Port:443 SrcAddr:0.0.0.0/0}:NATValue{ID:2,Count:0,LocalCount:0,AffinityTimeout:0,Flags:{}}
2023-10-25 04:43:10.974 [DEBUG][519655] felix/syncer.go 371: applied a service default/kubernetes:https update: sinfo={id:2 count:0 localCount:0 svc:0xc000001800}
@tomastigera I think I've found why this happens -
default kubernetes endpoint by default has label endpointslice.kubernetes.io/skip-mirror: "true"
when this label is set, for some reason, felix doesn't detect the endpoint IP - look at the debug logs:
felix/syncer.go 528: Applying new state,
{map[calico-apiserver/calico-api:apiserver:10.98.112.143:443/TCP calico-system/calico-typha:calico-typha:10.97.243.18:5473/TCP default/kubernetes:https:10.96.0.1:443/TCP kube-system/kube-dns:dns:10.96.0.10:53/UDP kube-system/kube-dns:dns-tcp:10.96.0.10:53/TCP kube-system/kube-dns:metrics:10.96.0.10:9153/TCP kube-system/metrics-server:https:10.111.92.186:443/TCP test/podinfo:grpc:10.101.221.237:9999/TCP test/podinfo:http:10.101.221.237:9898/TCP]
map[calico-apiserver/calico-api:apiserver:[192.168.22.147:5443 192.168.41.63:5443] calico-system/calico-typha:calico-typha:[172.21.35.21:5473 172.21.35.23:5473] kube-system/kube-dns:dns:[192.168.114.121:53 192.168.22.164:53] kube-system/kube-dns:dns-tcp:[192.168.114.121:53 192.168.22.164:53] kube-system/kube-dns:metrics:[192.168.114.121:9153 192.168.22.164:9153] kube-system/metrics-server:https:[192.168.22.151:10250] test/podinfo:grpc:[192.168.114.124:9999 192.168.22.167:9999 192.168.41.9:9999] test/podinfo:http:[192.168.114.124:9898 192.168.22.167:9898 192.168.41.9:9898]] }
The second map - with the endpoint IPs doesn't contain default/kubernetes! even though the endpoint itself has the IP:
[hawara@phoenix secrent-repo]$ k get endpoints -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Endpoints
metadata:
creationTimestamp: "2023-09-17T11:02:15Z"
labels:
endpointslice.kubernetes.io/skip-mirror: "true"
name: kubernetes
namespace: default
resourceVersion: "13585030"
uid: 065a580d-7c2a-41dd-a84a-1c5e7d7b9c66
subsets:
- addresses:
- ip: 172.21.35.10
ports:
- name: https
port: 6443
protocol: TCP
kind: List
metadata:
resourceVersion: ""
if I manually create the endpointslice, then it appears in felix's debug endpoint map:
2023-10-25 05:41:04.595 [DEBUG][527820] felix/syncer.go 528: Applying new state, {map[calico-apiserver/calico-api:apiserver:10.98.112.143:443/TCP calico-system/calico-typha:calico-typha:10.97.243.18:5473/TCP default/kubernetes:https:10.96.0.1:443/TCP kube-system/kube-dns:dns:10.96.0.10:53/UDP kube-system/kube-dns:dns-tcp:10.96.0.10:53/TCP kube-system/kube-dns:metrics:10.96.0.10:9153/TCP kube-system/metrics-server:https:10.111.92.186:443/TCP test/podinfo:grpc:10.101.221.237:9999/TCP test/podinfo:http:10.101.221.237:9898/TCP] map[calico-apiserver/calico-api:apiserver:[192.168.22.147:5443 192.168.41.63:5443] calico-system/calico-typha:calico-typha:[172.21.35.21:5473 172.21.35.23:5473] default/kubernetes:https:[172.21.35.10:6443] kube-system/kube-dns:dns:[192.168.114.121:53 192.168.22.164:53] kube-system/kube-dns:dns-tcp:[192.168.114.121:53 192.168.22.164:53] kube-system/kube-dns:metrics:[192.168.114.121:9153 192.168.22.164:9153] kube-system/metrics-server:https:[192.168.22.151:10250] test/podinfo:grpc:[192.168.114.124:9999 192.168.22.167:9999 192.168.41.9:9999] test/podinfo:http:[192.168.114.124:9898 192.168.22.167:9898 192.168.41.9:9898]] }
But this is not a solution - that label to not sync to endpointslices is set by the kube api server by default, if I'm not mistaken.
And I've checked - I have Felix config parameter bpfKubeProxyEndpointSlicesEnabled: false
- even though it's false by default. It doesn't matter, if it's set or not - the IP doesn't appear in the endpoint list, unless an endpointslice is present.
As a workaround, I'll create the endpointslice manually, but I still need your help, thank you.
Hey @mtb-xt great debugging!
Afaict Endpoints processing in kube-proxy is deprecated (see for instance here we also deprecated using endpoints in our kube-proxy. We use the k8s provides frontend package. The option you mentioned above bpfKubeProxyEndpointSlicesEnabled
is an cleanup omission, does not do anything and we will remove it.
This said, I am not sure if there is any other way then to configure your system so that it does not set this label endpointslice.kubernetes.io/skip-mirror: "true"
I wonder how does this behave with vanilla kubernetes, that is iptables dataplane and k8s provided kube-proxy. Was there any patch in k0s that would keep this functionality around?
I don't understand this anymore, I've recreated my cluster, set the externalAddress - and lo and behold, endpoint object DOES NOT contain that label.
I did look at what happens inside k0s and inside kubernetes itself - it looks like there is a condition, when the apiserver will set that label - https://github.com/kubernetes/kubernetes/blob/fd5c40611257c694d2338960976726344e2b45e5/pkg/controlplane/reconcilers/instancecount.go#L82
And k0s does nothing specific - it just creates these endpoints. Maybe, somehow, sometimes, it is possible that the line in apiserver adds that label. I'm not sure, but I think the issue ca be closed - at least there will be an info for a google search.
Does this mean that if the label is present it should be removed? I'm seeing similar behavior I believe. Calico is exporting the kubernetes service address, but not importing it.
Calico is exporting the kubernetes service address, but not importing it.
What do you mean by that?
I was wrong and the situation resolved itself. Ignore me. I was concerned that nodes were not BGP importing the service address for kubernetes itself. Looking at the routing table confirmed this, but I checked back later and things have started working. Does calico accept all route advertisements if there are no filters in place?
Hi everyone, I have a very strange issue (I'm not even 100% sure it's calico's fault) with my cluster's API service address 10.96.0.1. No pods can reach that address, and the error I'm getting is 'operation not permitted'.
I'm running a k0s cluster with manually configured Calico in eBPF mode. I have 3 control-plane servers and 3 workers (in libvirt virtual machines, with bridged networking).
I have installed Calico using the operator, according to the manual. Everything was working fine, while I had 1 cp and 1 worker. After adding more controlplane nodes to the cluster, I started having this issue.
For example, with coredns -
I'm not 100% sure, but the issue seem to start after I added an external loadbalancer to the API. k0s requires having an external loadbalancer in front of highly-available control planes, so I have a keepalived virtual ip + haproxy loadbalancer on every control plane - this virtual IP is configured in both k0s and in tigera operator kubernetes-services-endpoint configmap, like so:
I've tried figuring out the issue myself, and what I found - is that for the service IP, there is no 'backend' in BPF nat:
Not sure what to do next, or how to debug this further.
Expected Behavior
Kubernetes service API is accessible.
Current Behavior
Pods can't talk to the API server internally -
dial tcp 10.96.0.1:443: connect: operation not permitted
Possible Solution
Really no idea what causes it :(
Steps to Reproduce (for bugs)
Context
Your Environment
Thank you, and please let me know if you need any more details.