-
Notifications
You must be signed in to change notification settings - Fork 7
/
member.go
166 lines (150 loc) · 5.97 KB
/
member.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package etcd
import (
"fmt"
"github.com/flexkube/libflexkube/pkg/container"
"github.com/flexkube/libflexkube/pkg/container/runtime/docker"
containertypes "github.com/flexkube/libflexkube/pkg/container/types"
"github.com/flexkube/libflexkube/pkg/defaults"
"github.com/flexkube/libflexkube/pkg/host"
"github.com/flexkube/libflexkube/pkg/types"
)
// Member represents single etcd member
type Member struct {
Name string `json:"name" yaml:"name"`
Image string `json:"image" yaml:"image"`
Host host.Host `json:"host" yaml:"host"`
CACertificate types.Certificate `json:"caCertificate" yaml:"caCertificate"`
PeerCertificate types.Certificate `json:"peerCertificate" yaml:"peerCertificate"`
PeerKey types.PrivateKey `json:"peerKey" yaml:"peerKey"`
PeerAddress string `json:"peerAddress" yaml:"peerAddress"`
InitialCluster string `json:"initialCluster" yaml:"initialCluster"`
PeerCertAllowedCN string `json:"peerCertAllowedCN" yaml:"peerCertAllowedCN"`
ServerCertificate types.Certificate `json:"serverCertificate" yaml:"serverCertificate"`
ServerKey types.PrivateKey `json:"serverKey" yaml:"serverKey"`
ServerAddress string `json:"serverAddress" yaml:"serverAddress"`
}
// member is a validated, executable version of Member
type member struct {
name string
image string
host host.Host
caCertificate string
peerCertificate string
peerKey string
peerAddress string
initialCluster string
peerCertAllowedCN string
serverCertificate string
serverKey string
serverAddress string
}
func (m *member) configFiles() map[string]string {
return map[string]string{
"/etc/kubernetes/etcd/ca.crt": m.caCertificate,
"/etc/kubernetes/etcd/peer.crt": m.peerCertificate,
"/etc/kubernetes/etcd/peer.key": m.peerKey,
"/etc/kubernetes/etcd/server.crt": m.serverCertificate,
"/etc/kubernetes/etcd/server.key": m.serverKey,
}
}
// ToHostConfiguredContainer takes configured member and converts it to generic HostConfiguredContainer
func (m *member) ToHostConfiguredContainer() (*container.HostConfiguredContainer, error) {
c := container.Container{
// TODO this is weird. This sets docker as default runtime config
Runtime: container.RuntimeConfig{
Docker: &docker.Config{},
},
Config: containertypes.ContainerConfig{
Name: m.name,
Image: m.image,
Entrypoint: []string{"/usr/local/bin/etcd"},
Mounts: []containertypes.Mount{
{
// TODO between /var/lib/etcd and data dir we should probably put cluster name, to group them
// TODO make data dir configurable
Source: fmt.Sprintf("/var/lib/etcd/%s.etcd/", m.name),
Target: fmt.Sprintf("/%s.etcd", m.name),
},
{
Source: "/etc/kubernetes/etcd/",
Target: "/etc/kubernetes/pki/etcd",
},
},
NetworkMode: "host",
Args: []string{
//TODO Add descriptions explaining why we need each line.
// Default value 'capnslog' for logger is deprecated and prints warning now.
//"--logger=zap", // Available only from 3.4.x
// Since we are in container, listen on all interfaces
fmt.Sprintf("--listen-client-urls=https://%s:2379", m.serverAddress),
fmt.Sprintf("--listen-peer-urls=https://%s:2380", m.peerAddress),
fmt.Sprintf("--advertise-client-urls=https://%s:2379", m.serverAddress),
fmt.Sprintf("--initial-advertise-peer-urls=https://%s:2380", m.peerAddress),
fmt.Sprintf("--initial-cluster=%s", m.initialCluster),
fmt.Sprintf("--name=%s", m.name),
"--initial-cluster-token=etcd-cluster-2",
"--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt",
"--peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt",
"--peer-key-file=/etc/kubernetes/pki/etcd/peer.key",
"--peer-client-cert-auth",
"--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt",
"--cert-file=/etc/kubernetes/pki/etcd/server.crt",
"--key-file=/etc/kubernetes/pki/etcd/server.key",
fmt.Sprintf("--data-dir=/%s.etcd", m.name),
// To get rid of warning with default configuration.
// ttl parameter support has been added in 3.4.x
"--auth-token=jwt,pub-key=/etc/kubernetes/pki/etcd/peer.crt,priv-key=/etc/kubernetes/pki/etcd/peer.key,sign-method=RS512,ttl=10m",
// This is set by typhoon, seems like extra safety knob
"--strict-reconfig-check",
// TODO enable metrics
},
},
}
return &container.HostConfiguredContainer{
Host: m.host,
ConfigFiles: m.configFiles(),
Container: c,
}, nil
}
// New valides Member configuration and returns it's usable version
func (m *Member) New() (container.ResourceInstance, error) {
if err := m.Validate(); err != nil {
return nil, fmt.Errorf("failed to validate member configuration: %w", err)
}
nm := &member{
name: m.Name,
image: m.Image,
host: m.Host,
caCertificate: string(m.CACertificate),
peerCertificate: string(m.PeerCertificate),
peerKey: string(m.PeerKey),
peerAddress: m.PeerAddress,
initialCluster: m.InitialCluster,
peerCertAllowedCN: m.PeerCertAllowedCN,
serverCertificate: string(m.ServerCertificate),
serverKey: string(m.ServerKey),
serverAddress: m.ServerAddress,
}
if nm.image == "" {
nm.image = defaults.EtcdImage
}
return nm, nil
}
// Validate validates etcd member configuration
// TODO add validation of certificates if specified
func (m *Member) Validate() error {
var errors types.ValidateError
// TODO require peer address for now. Later we could figure out
// how to use CNI for setting it using env variables or something
if m.PeerAddress == "" {
errors = append(errors, fmt.Errorf("peer address must be set"))
}
// TODO can we auto-generate it?
if m.Name == "" {
errors = append(errors, fmt.Errorf("member name must be set"))
}
if err := m.Host.Validate(); err != nil {
errors = append(errors, fmt.Errorf("host validation failed: %w", err))
}
return errors.Return()
}