Andrey Smirnov 0aaf8fa968 feat: replace bootkube with Talos-managed control plane
Control plane components are running as static pods managed by the
kubelets.

Whole subsystem is managed via resources/controllers from os-runtime.

Many supporting changes/refactoring to enable new code paths.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2021-01-26 14:22:35 -08:00

94 lines
2.2 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package kubelet provides minimal client for the kubelet API.
package kubelet
import (
"context"
"crypto/tls"
stdx509 "crypto/x509"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
v1 "k8s.io/api/core/v1"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// Client is a kubelet API client.
//
// Client can only talk to the local kubelet on the same node.
type Client struct {
httpClient *http.Client
hostname string
}
// NewClient creates new kubelet API client.
func NewClient(clientCert tls.Certificate) (*Client, error) {
rootCAs := stdx509.NewCertPool()
kubeletCert, err := ioutil.ReadFile(filepath.Join(constants.KubeletPKIDir, "kubelet.crt"))
if err != nil {
return nil, fmt.Errorf("error reading kubelet certificate: %w", err)
}
rootCAs.AppendCertsFromPEM(kubeletCert)
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: rootCAs,
}
client := &Client{
httpClient: &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
},
}
client.hostname, err = os.Hostname()
if err != nil {
return nil, err
}
return client, nil
}
// Pods returns list of pods running on the kubelet.
func (c *Client) Pods(ctx context.Context) (*v1.PodList, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s:%d/pods", c.hostname, constants.KubeletPort), nil)
if err != nil {
return nil, fmt.Errorf("error building request: %w", err)
}
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing request: %w", err)
}
defer func() {
io.Copy(ioutil.Discard, resp.Body) //nolint: errcheck
resp.Body.Close() //nolint: errcheck
}()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status response %d", resp.StatusCode)
}
var podList v1.PodList
if err = json.NewDecoder(resp.Body).Decode(&podList); err != nil {
return nil, fmt.Errorf("error decoding JSON response: %w", err)
}
return &podList, nil
}