blob: bd0d21152762a919a5f484dfe4fd7e453501e1a9 [file] [log] [blame]
Lorenz Brun6e8f69c2019-11-18 10:44:24 +01001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package kubernetes
18
19import (
Lorenz Brun878f5f92020-05-12 16:15:39 +020020 "context"
Serge Bazanskidbfc6382020-06-19 20:35:43 +020021 "fmt"
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010022 "net"
Serge Bazanskidbfc6382020-06-19 20:35:43 +020023 "os"
Lorenz Brunb15abad2020-04-16 11:17:12 +020024 "time"
25
Lorenz Brun878f5f92020-05-12 16:15:39 +020026 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
Lorenz Brunf042e6f2020-06-24 16:46:09 +020028 "k8s.io/client-go/informers"
Lorenz Brunb15abad2020-04-16 11:17:12 +020029 "k8s.io/client-go/kubernetes"
Lorenz Brunf042e6f2020-06-24 16:46:09 +020030 "k8s.io/client-go/tools/clientcmd"
Lorenz Brun878f5f92020-05-12 16:15:39 +020031
Serge Bazanski31370b02021-01-07 16:31:14 +010032 "source.monogon.dev/metropolis/node/core/localstorage"
33 "source.monogon.dev/metropolis/node/core/network/dns"
34 "source.monogon.dev/metropolis/node/kubernetes/clusternet"
35 "source.monogon.dev/metropolis/node/kubernetes/nfproxy"
36 "source.monogon.dev/metropolis/node/kubernetes/pki"
Lorenz Brun4e090352021-03-17 17:44:41 +010037 "source.monogon.dev/metropolis/node/kubernetes/plugins/kvmdevice"
Serge Bazanski31370b02021-01-07 16:31:14 +010038 "source.monogon.dev/metropolis/node/kubernetes/reconciler"
39 "source.monogon.dev/metropolis/pkg/supervisor"
40 apb "source.monogon.dev/metropolis/proto/api"
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010041)
42
43type Config struct {
44 AdvertiseAddress net.IP
45 ServiceIPRange net.IPNet
46 ClusterNet net.IPNet
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020047
Serge Bazanski9411f7c2021-03-10 13:12:53 +010048 KPKI *pki.PKI
Lorenz Brunfa5c2fc2020-09-28 13:32:12 +020049 Root *localstorage.Root
50 CorednsRegistrationChan chan *dns.ExtraDirective
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010051}
52
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020053type Service struct {
Serge Bazanski967be212020-11-02 11:26:59 +010054 c Config
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020055}
Serge Bazanskidbfc6382020-06-19 20:35:43 +020056
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020057func New(c Config) *Service {
58 s := &Service{
59 c: c,
60 }
61 return s
62}
63
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020064func (s *Service) Run(ctx context.Context) error {
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020065 controllerManagerConfig, err := getPKIControllerManagerConfig(ctx, s.c.KPKI)
66 if err != nil {
67 return fmt.Errorf("could not generate controller manager pki config: %w", err)
68 }
69 controllerManagerConfig.clusterNet = s.c.ClusterNet
70 schedulerConfig, err := getPKISchedulerConfig(ctx, s.c.KPKI)
71 if err != nil {
72 return fmt.Errorf("could not generate scheduler pki config: %w", err)
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010073 }
Serge Bazanskidbfc6382020-06-19 20:35:43 +020074
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020075 masterKubeconfig, err := s.c.KPKI.Kubeconfig(ctx, pki.Master)
76 if err != nil {
77 return fmt.Errorf("could not generate master kubeconfig: %w", err)
78 }
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010079
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020080 rawClientConfig, err := clientcmd.NewClientConfigFromBytes(masterKubeconfig)
81 if err != nil {
82 return fmt.Errorf("could not generate kubernetes client config: %w", err)
83 }
Lorenz Brun6e8f69c2019-11-18 10:44:24 +010084
Serge Bazanskic2c7ad92020-07-13 17:20:09 +020085 clientConfig, err := rawClientConfig.ClientConfig()
86 clientSet, err := kubernetes.NewForConfig(clientConfig)
87 if err != nil {
88 return fmt.Errorf("could not generate kubernetes client: %w", err)
89 }
90
91 informerFactory := informers.NewSharedInformerFactory(clientSet, 5*time.Minute)
92
93 hostname, err := os.Hostname()
94 if err != nil {
95 return fmt.Errorf("failed to get hostname: %w", err)
96 }
97
Lorenz Brun339582b2020-07-29 18:13:35 +020098 dnsHostIP := s.c.AdvertiseAddress // TODO: Which IP to use
99
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200100 apiserver := &apiserverService{
101 KPKI: s.c.KPKI,
102 AdvertiseAddress: s.c.AdvertiseAddress,
103 ServiceIPRange: s.c.ServiceIPRange,
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200104 EphemeralConsensusDirectory: &s.c.Root.Ephemeral.Consensus,
105 }
106
107 kubelet := kubeletService{
108 NodeName: hostname,
Lorenz Brun339582b2020-07-29 18:13:35 +0200109 ClusterDNS: []net.IP{dnsHostIP},
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200110 KubeletDirectory: &s.c.Root.Data.Kubernetes.Kubelet,
111 EphemeralDirectory: &s.c.Root.Ephemeral,
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200112 KPKI: s.c.KPKI,
113 }
114
115 csiPlugin := csiPluginServer{
116 KubeletDirectory: &s.c.Root.Data.Kubernetes.Kubelet,
117 VolumesDirectory: &s.c.Root.Data.Volumes,
118 }
119
120 csiProvisioner := csiProvisionerServer{
121 NodeName: hostname,
122 Kubernetes: clientSet,
123 InformerFactory: informerFactory,
124 VolumesDirectory: &s.c.Root.Data.Volumes,
125 }
126
127 clusternet := clusternet.Service{
128 NodeName: hostname,
129 Kubernetes: clientSet,
130 ClusterNet: s.c.ClusterNet,
131 InformerFactory: informerFactory,
132 DataDirectory: &s.c.Root.Data.Kubernetes.ClusterNetworking,
133 }
134
Lorenz Brunb682ba52020-07-08 14:51:36 +0200135 nfproxy := nfproxy.Service{
136 ClusterCIDR: s.c.ClusterNet,
137 ClientSet: clientSet,
138 }
139
Lorenz Brun4e090352021-03-17 17:44:41 +0100140 kvmDevicePlugin := kvmdevice.Plugin{
141 KubeletDirectory: &s.c.Root.Data.Kubernetes.Kubelet,
142 }
143
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200144 for _, sub := range []struct {
145 name string
146 runnable supervisor.Runnable
147 }{
148 {"apiserver", apiserver.Run},
Serge Bazanski967be212020-11-02 11:26:59 +0100149 {"controller-manager", runControllerManager(*controllerManagerConfig)},
150 {"scheduler", runScheduler(*schedulerConfig)},
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200151 {"kubelet", kubelet.Run},
152 {"reconciler", reconciler.Run(clientSet)},
153 {"csi-plugin", csiPlugin.Run},
154 {"csi-provisioner", csiProvisioner.Run},
155 {"clusternet", clusternet.Run},
Lorenz Brunb682ba52020-07-08 14:51:36 +0200156 {"nfproxy", nfproxy.Run},
Lorenz Brun4e090352021-03-17 17:44:41 +0100157 {"kvmdeviceplugin", kvmDevicePlugin.Run},
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200158 } {
159 err := supervisor.Run(ctx, sub.name, sub.runnable)
160 if err != nil {
161 return fmt.Errorf("could not run sub-service %q: %w", sub.name, err)
162 }
163 }
164
Lorenz Brunfa5c2fc2020-09-28 13:32:12 +0200165 supervisor.Logger(ctx).Info("Registering K8s CoreDNS")
166 clusterDNSDirective := dns.NewKubernetesDirective("cluster.local", masterKubeconfig)
167 s.c.CorednsRegistrationChan <- clusterDNSDirective
168
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200169 supervisor.Signal(ctx, supervisor.SignalHealthy)
Lorenz Brunfa5c2fc2020-09-28 13:32:12 +0200170 <-ctx.Done()
171 s.c.CorednsRegistrationChan <- dns.CancelDirective(clusterDNSDirective)
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200172 return nil
Lorenz Brun6e8f69c2019-11-18 10:44:24 +0100173}
174
Lorenz Brun878f5f92020-05-12 16:15:39 +0200175// GetDebugKubeconfig issues a kubeconfig for an arbitrary given identity. Useful for debugging and testing.
Serge Bazanskic2c7ad92020-07-13 17:20:09 +0200176func (s *Service) GetDebugKubeconfig(ctx context.Context, request *apb.GetDebugKubeconfigRequest) (*apb.GetDebugKubeconfigResponse, error) {
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100177 client, err := s.c.KPKI.VolatileClient(ctx, request.Id, request.Groups)
178 if err != nil {
179 return nil, status.Errorf(codes.Unavailable, "Failed to get volatile client certificate: %v", err)
180 }
181 kubeconfig, err := pki.Kubeconfig(ctx, s.c.KPKI.KV, client)
Lorenz Brun878f5f92020-05-12 16:15:39 +0200182 if err != nil {
183 return nil, status.Errorf(codes.Unavailable, "Failed to generate kubeconfig: %v", err)
184 }
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100185 return &apb.GetDebugKubeconfigResponse{DebugKubeconfig: string(kubeconfig)}, nil
Lorenz Brun6e8f69c2019-11-18 10:44:24 +0100186}