Skip to content

Commit 0de1b2d

Browse files
authored
Merge pull request #794 from brownleej/ipv6
Pod IP selection rules for dual-stack environments
2 parents 731420b + fe13130 commit 0de1b2d

21 files changed

+634
-97
lines changed

api/v1beta1/foundationdbcluster_types.go

+45-12
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,12 @@ type FoundationDBClusterSpec struct {
166166

167167
// Services defines the configuration for services that sit in front of our
168168
// pods.
169+
// Deprecated: Use Routing instead.
169170
Services ServiceConfig `json:"services,omitempty"`
170171

172+
// Routing defines the configuration for routing to our pods.
173+
Routing RoutingConfig `json:"routing,omitempty"`
174+
171175
// IgnoreUpgradabilityChecks determines whether we should skip the check for
172176
// client compatibility when performing an upgrade.
173177
IgnoreUpgradabilityChecks bool `json:"ignoreUpgradabilityChecks,omitempty"`
@@ -1568,23 +1572,28 @@ type ProcessAddress struct {
15681572
// representation.
15691573
func ParseProcessAddress(address string) (ProcessAddress, error) {
15701574
result := ProcessAddress{}
1571-
components := strings.Split(address, ":")
15721575

1573-
if len(components) < 2 {
1576+
ipEnd := strings.Index(address, "]:") + 1
1577+
if ipEnd == 0 {
1578+
ipEnd = strings.Index(address, ":")
1579+
}
1580+
if ipEnd == -1 {
15741581
return result, fmt.Errorf("invalid address: %s", address)
15751582
}
15761583

1577-
result.IPAddress = components[0]
1584+
result.IPAddress = address[:ipEnd]
15781585

1579-
port, err := strconv.Atoi(components[1])
1586+
components := strings.Split(address[ipEnd+1:], ":")
1587+
1588+
port, err := strconv.Atoi(components[0])
15801589
if err != nil {
15811590
return result, err
15821591
}
15831592
result.Port = port
15841593

1585-
if len(components) > 2 {
1586-
result.Flags = make(map[string]bool, len(components)-2)
1587-
for _, flag := range components[2:] {
1594+
if len(components) > 1 {
1595+
result.Flags = make(map[string]bool, len(components)-1)
1596+
for _, flag := range components[1:] {
15881597
result.Flags[flag] = true
15891598
}
15901599
}
@@ -1813,10 +1822,13 @@ type DataCenter struct {
18131822
// ContainerOverrides provides options for customizing a container created by
18141823
// the operator.
18151824
type ContainerOverrides struct {
1816-
// EnableLivenessProbe defines if the sidecar should have a livenessProbe in addition
1817-
// to the readinessProbe. This setting will be enabled per default in the 1.0.0 release.
1825+
// EnableLivenessProbe defines if the sidecar should have a livenessProbe.
1826+
// This setting will be ignored on the main container.
1827+
EnableLivenessProbe *bool `json:"enableLivenessProbe,omitempty"`
1828+
1829+
// EnableReadinessProbe defines if the sidecar should have a readinessProbe.
18181830
// This setting will be ignored on the main container.
1819-
EnableLivenessProbe bool `json:"enableLivenessProbe,omitempty"`
1831+
EnableReadinessProbe *bool `json:"enableReadinessProbe,omitempty"`
18201832

18211833
// EnableTLS controls whether we should be listening on a TLS connection.
18221834
EnableTLS bool `json:"enableTls,omitempty"`
@@ -1994,13 +2006,13 @@ func (cluster *FoundationDBCluster) GetLockID() string {
19942006
// NeedsExplicitListenAddress determines whether we pass a listen address
19952007
// parameter to fdbserver.
19962008
func (cluster *FoundationDBCluster) NeedsExplicitListenAddress() bool {
1997-
source := cluster.Spec.Services.PublicIPSource
2009+
source := cluster.Spec.Routing.PublicIPSource
19982010
return source != nil && *source == PublicIPSourceService
19992011
}
20002012

20012013
// GetPublicIPSource returns the set PublicIPSource or the default PublicIPSourcePod
20022014
func (cluster *FoundationDBCluster) GetPublicIPSource() PublicIPSource {
2003-
source := cluster.Spec.Services.PublicIPSource
2015+
source := cluster.Spec.Routing.PublicIPSource
20042016
if source == nil {
20052017
return PublicIPSourcePod
20062018
}
@@ -2383,6 +2395,7 @@ type LockDenyListEntry struct {
23832395
}
23842396

23852397
// ServiceConfig allows configuring services that sit in front of our pods.
2398+
// Deprecated: Use RoutingConfig instead.
23862399
type ServiceConfig struct {
23872400
// Headless determines whether we want to run a headless service for the
23882401
// cluster.
@@ -2395,6 +2408,26 @@ type ServiceConfig struct {
23952408
PublicIPSource *PublicIPSource `json:"publicIPSource,omitempty"`
23962409
}
23972410

2411+
// RoutingConfig allows configuring routing to our pods, and services that sit
2412+
// in front of them.
2413+
type RoutingConfig struct {
2414+
// Headless determines whether we want to run a headless service for the
2415+
// cluster.
2416+
HeadlessService *bool `json:"headlessService,omitempty"`
2417+
2418+
// PublicIPSource specifies what source a process should use to get its
2419+
// public IPs.
2420+
//
2421+
// This supports the values `pod` and `service`.
2422+
PublicIPSource *PublicIPSource `json:"publicIPSource,omitempty"`
2423+
2424+
// PodIPFamily tells the pod which family of IP addresses to use.
2425+
// You can use 4 to represent IPv4, and 6 to represent IPv6.
2426+
// This feature is only supported in FDB 7.0 or later, and requires
2427+
// dual-stack support in your Kubernetes environment.
2428+
PodIPFamily *int `json:"podIPFamily,omitempty"`
2429+
}
2430+
23982431
// RequiredAddressSet provides settings for which addresses we need to listen
23992432
// on.
24002433
type RequiredAddressSet struct {

api/v1beta1/foundationdbcluster_types_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,14 @@ var _ = Describe("[api] FoundationDBCluster", func() {
22762276
}))
22772277
Expect(address.String()).To(Equal("127.0.0.1:4501"))
22782278

2279+
address, err = ParseProcessAddress("[::1]:4501")
2280+
Expect(err).NotTo(HaveOccurred())
2281+
Expect(address).To(Equal(ProcessAddress{
2282+
IPAddress: "[::1]",
2283+
Port: 4501,
2284+
}))
2285+
Expect(address.String()).To(Equal("[::1]:4501"))
2286+
22792287
address, err = ParseProcessAddress("127.0.0.1:bad")
22802288
Expect(err).To(HaveOccurred())
22812289
Expect(err.Error()).To(Equal("strconv.Atoi: parsing \"bad\": invalid syntax"))
@@ -2810,6 +2818,19 @@ var _ = Describe("[api] FoundationDBCluster", func() {
28102818
},
28112819
},
28122820
}),
2821+
Entry("TLS IPv6",
2822+
testCase{
2823+
cmdline: "/usr/bin/fdbserver --class=stateless --cluster_file=/var/fdb/data/fdb.cluster --datadir=/var/fdb/data --locality_instance_id=stateless-9 --locality_machineid=machine1 --locality_zoneid=zone1 --logdir=/var/log/fdb-trace-logs --loggroup=test --public_address=[::1]:4500:tls --seed_cluster_file=/var/dynamic-conf/fdb.cluster",
2824+
expected: []ProcessAddress{
2825+
{
2826+
IPAddress: "[::1]",
2827+
Port: 4500,
2828+
Flags: map[string]bool{
2829+
"tls": true,
2830+
},
2831+
},
2832+
},
2833+
}),
28132834
Entry("TLS and no-TLS",
28142835
testCase{
28152836
cmdline: "/usr/bin/fdbserver --class=stateless --cluster_file=/var/fdb/data/fdb.cluster --datadir=/var/fdb/data --locality_instance_id=stateless-9 --locality_machineid=machine1 --locality_zoneid=zone1 --logdir=/var/log/fdb-trace-logs --loggroup=test --public_address=1.2.3.4:4501,1.2.3.4:4500:tls --seed_cluster_file=/var/dynamic-conf/fdb.cluster",

api/v1beta1/zz_generated.deepcopy.go

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/apps.foundationdb.org_foundationdbclusters.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,8 @@ spec:
13201320
properties:
13211321
enableLivenessProbe:
13221322
type: boolean
1323+
enableReadinessProbe:
1324+
type: boolean
13231325
enableTls:
13241326
type: boolean
13251327
env:
@@ -7564,6 +7566,15 @@ spec:
75647566
x-kubernetes-int-or-string: true
75657567
type: object
75667568
type: object
7569+
routing:
7570+
properties:
7571+
headlessService:
7572+
type: boolean
7573+
podIPFamily:
7574+
type: integer
7575+
publicIPSource:
7576+
type: string
7577+
type: object
75677578
runningVersion:
75687579
type: string
75697580
seedConnectionString:
@@ -7579,6 +7590,8 @@ spec:
75797590
properties:
75807591
enableLivenessProbe:
75817592
type: boolean
7593+
enableReadinessProbe:
7594+
type: boolean
75827595
enableTls:
75837596
type: boolean
75847597
env:

config/tests/base/cluster.yaml

+6-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ spec:
88
# Use fake fault domains to support running in a single-node Kubernetes
99
# cluster.
1010
key: foundationdb.org/none
11-
services:
12-
headless: true
11+
routing:
12+
headlessService: true
1313
automationOptions:
1414
replacements:
1515
# Enable automatic replacements. This will be the default in the future.
@@ -20,6 +20,10 @@ spec:
2020
# Enable a dedicated cluster controller process to test for surprising
2121
# behavior with having a process class with an underscore.
2222
cluster_controller: 1
23+
sidecarContainer:
24+
# Change default probes to match the defaults we will apply in the future.
25+
enableReadinessProbe: false
26+
enableLivenessProbe: true
2327
processes:
2428
general:
2529
customParameters:

controllers/add_pods.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func (a AddPods) Reconcile(r *FoundationDBClusterReconciler, context ctx.Context
8787

8888
pod.ObjectMeta.Annotations[fdbtypes.LastConfigMapKey] = configMapHash
8989

90-
if *cluster.Spec.Services.PublicIPSource == fdbtypes.PublicIPSourceService {
90+
if *cluster.Spec.Routing.PublicIPSource == fdbtypes.PublicIPSourceService {
9191
service := &corev1.Service{}
9292
err = r.Get(context, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, service)
9393
if err != nil {

controllers/add_services.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (a AddServices) Reconcile(r *FoundationDBClusterReconciler, context ctx.Con
5252
}
5353
}
5454

55-
if *cluster.Spec.Services.PublicIPSource == fdbtypes.PublicIPSourceService {
55+
if *cluster.Spec.Routing.PublicIPSource == fdbtypes.PublicIPSourceService {
5656
for _, processGroup := range cluster.Status.ProcessGroups {
5757
if processGroup.Remove {
5858
continue
@@ -90,7 +90,7 @@ func (a AddServices) Reconcile(r *FoundationDBClusterReconciler, context ctx.Con
9090

9191
// GetHeadlessService builds a headless service for a FoundationDB cluster.
9292
func GetHeadlessService(cluster *fdbtypes.FoundationDBCluster) *corev1.Service {
93-
headless := cluster.Spec.Services.Headless
93+
headless := cluster.Spec.Routing.HeadlessService
9494
if headless == nil || !*headless {
9595
return nil
9696
}

controllers/add_services_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ var _ = Describe("add_services", func() {
4242
BeforeEach(func() {
4343
cluster = createDefaultCluster()
4444
source := fdbtypes.PublicIPSourceService
45-
cluster.Spec.Services.PublicIPSource = &source
45+
cluster.Spec.Routing.PublicIPSource = &source
4646
enabled := true
47-
cluster.Spec.Services.Headless = &enabled
47+
cluster.Spec.Routing.HeadlessService = &enabled
4848

4949
err = k8sClient.Create(context.TODO(), cluster)
5050
Expect(err).NotTo(HaveOccurred())
@@ -108,7 +108,7 @@ var _ = Describe("add_services", func() {
108108
Context("with the pod public IP source", func() {
109109
BeforeEach(func() {
110110
source := fdbtypes.PublicIPSourcePod
111-
cluster.Spec.Services.PublicIPSource = &source
111+
cluster.Spec.Routing.PublicIPSource = &source
112112
})
113113

114114
It("should not requeue", func() {
@@ -161,7 +161,7 @@ var _ = Describe("add_services", func() {
161161
Context("with the headless service disabled", func() {
162162
BeforeEach(func() {
163163
enabled := false
164-
cluster.Spec.Services.Headless = &enabled
164+
cluster.Spec.Routing.HeadlessService = &enabled
165165
})
166166

167167
It("should not requeue", func() {

0 commit comments

Comments
 (0)