Skip to content

Commit 5c3eb3c

Browse files
authored
fix: hanging the adc program can cause the k8s client to exceed its limit (#104)
1 parent 8b0f874 commit 5c3eb3c

File tree

5 files changed

+33
-21
lines changed

5 files changed

+33
-21
lines changed

config/samples/config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ leader_election:
1515
retry_period: 2s # retry_period is the time in seconds that the acting controller
1616
# will wait between tries of actions with the controller.
1717
disable: false # Whether to disable leader election.
18+
19+
exec_adc_timeout: 15s # The timeout for the ADC to execute.
20+
# The default value is 15 seconds.

examples/httpbin/ingress.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ spec:
3434
apiVersion: networking.k8s.io/v1
3535
kind: Ingress
3636
metadata:
37-
name: api7-ingress-tls
37+
name: api7-ingress
3838
spec:
3939
ingressClassName: api7
4040
rules:

internal/controller/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func NewDefaultConfig() *Config {
3131
ProbeAddr: DefaultProbeAddr,
3232
MetricsAddr: DefaultMetricsAddr,
3333
LeaderElection: NewLeaderElection(),
34+
ExecADCTimeout: types.TimeDuration{Duration: 15 * time.Second},
3435
}
3536
}
3637

internal/controller/config/types.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@ const (
2424
// Config contains all config items which are necessary for
2525
// apisix-ingress-controller's running.
2626
type Config struct {
27-
CertFilePath string `json:"cert_file" yaml:"cert_file"`
28-
KeyFilePath string `json:"key_file" yaml:"key_file"`
29-
LogLevel string `json:"log_level" yaml:"log_level"`
30-
ControllerName string `json:"controller_name" yaml:"controller_name"`
31-
LeaderElectionID string `json:"leader_election_id" yaml:"leader_election_id"`
32-
MetricsAddr string `json:"metrics_addr" yaml:"metrics_addr"`
33-
EnableHTTP2 bool `json:"enable_http2" yaml:"enable_http2"`
34-
ProbeAddr string `json:"probe_addr" yaml:"probe_addr"`
35-
SecureMetrics bool `json:"secure_metrics" yaml:"secure_metrics"`
36-
LeaderElection *LeaderElection `json:"leader_election" yaml:"leader_election"`
27+
CertFilePath string `json:"cert_file" yaml:"cert_file"`
28+
KeyFilePath string `json:"key_file" yaml:"key_file"`
29+
LogLevel string `json:"log_level" yaml:"log_level"`
30+
ControllerName string `json:"controller_name" yaml:"controller_name"`
31+
LeaderElectionID string `json:"leader_election_id" yaml:"leader_election_id"`
32+
MetricsAddr string `json:"metrics_addr" yaml:"metrics_addr"`
33+
EnableHTTP2 bool `json:"enable_http2" yaml:"enable_http2"`
34+
ProbeAddr string `json:"probe_addr" yaml:"probe_addr"`
35+
SecureMetrics bool `json:"secure_metrics" yaml:"secure_metrics"`
36+
LeaderElection *LeaderElection `json:"leader_election" yaml:"leader_election"`
37+
ExecADCTimeout types.TimeDuration `json:"exec_adc_timeout" yaml:"exec_adc_timeout"`
3738
}
3839

3940
type GatewayConfig struct {

internal/provider/adc/adc.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"os/exec"
1010
"sync"
11+
"time"
1112

1213
"go.uber.org/zap"
1314
networkingv1 "k8s.io/api/networking/v1"
@@ -16,6 +17,7 @@ import (
1617

1718
adctypes "github.com/api7/api7-ingress-controller/api/adc"
1819
"github.com/api7/api7-ingress-controller/api/v1alpha1"
20+
"github.com/api7/api7-ingress-controller/internal/controller/config"
1921
"github.com/api7/api7-ingress-controller/internal/controller/label"
2022
"github.com/api7/api7-ingress-controller/internal/provider"
2123
"github.com/api7/api7-ingress-controller/internal/provider/adc/translator"
@@ -38,6 +40,8 @@ type adcClient struct {
3840
configs map[provider.ResourceKind]adcConfig
3941
// httproute/consumer/ingress/gateway -> gateway/ingressclass
4042
parentRefs map[provider.ResourceKind][]provider.ResourceKind
43+
44+
syncTimeout time.Duration
4145
}
4246

4347
type Task struct {
@@ -50,9 +54,10 @@ type Task struct {
5054

5155
func New() (provider.Provider, error) {
5256
return &adcClient{
53-
translator: &translator.Translator{},
54-
configs: make(map[provider.ResourceKind]adcConfig),
55-
parentRefs: make(map[provider.ResourceKind][]provider.ResourceKind),
57+
syncTimeout: config.ControllerConfig.ExecADCTimeout.Duration,
58+
translator: &translator.Translator{},
59+
configs: make(map[provider.ResourceKind]adcConfig),
60+
parentRefs: make(map[provider.ResourceKind][]provider.ResourceKind),
5661
}, nil
5762
}
5863

@@ -101,7 +106,7 @@ func (d *adcClient) Update(ctx context.Context, tctx *provider.TranslateContext,
101106

102107
// sync delete
103108
if len(deleteConfigs) > 0 {
104-
err = d.sync(Task{
109+
err = d.sync(ctx, Task{
105110
Name: obj.GetName(),
106111
Labels: label.GenLabel(obj),
107112
ResourceTypes: resourceTypes,
@@ -113,7 +118,7 @@ func (d *adcClient) Update(ctx context.Context, tctx *provider.TranslateContext,
113118
}
114119

115120
// sync update
116-
err = d.sync(Task{
121+
err = d.sync(ctx, Task{
117122
Name: obj.GetName(),
118123
Labels: label.GenLabel(obj),
119124
Resources: adctypes.Resources{
@@ -160,7 +165,7 @@ func (d *adcClient) Delete(ctx context.Context, obj client.Object) error {
160165

161166
configs := d.getConfigs(rk)
162167

163-
err := d.sync(Task{
168+
err := d.sync(ctx, Task{
164169
Name: obj.GetName(),
165170
Labels: labels,
166171
ResourceTypes: resourceTypes,
@@ -174,7 +179,7 @@ func (d *adcClient) Delete(ctx context.Context, obj client.Object) error {
174179
return nil
175180
}
176181

177-
func (d *adcClient) sync(task Task) error {
182+
func (d *adcClient) sync(ctx context.Context, task Task) error {
178183
log.Debugw("syncing resources", zap.Any("task", task))
179184

180185
if len(task.configs) == 0 {
@@ -216,15 +221,17 @@ func (d *adcClient) sync(task Task) error {
216221

217222
log.Debugw("syncing resources with multiple configs", zap.Any("configs", task.configs))
218223
for _, config := range task.configs {
219-
if err := d.execADC(config, args); err != nil {
224+
if err := d.execADC(ctx, config, args); err != nil {
220225
return err
221226
}
222227
}
223228

224229
return nil
225230
}
226231

227-
func (d *adcClient) execADC(config adcConfig, args []string) error {
232+
func (d *adcClient) execADC(ctx context.Context, config adcConfig, args []string) error {
233+
ctxWithTimeout, cancel := context.WithTimeout(ctx, d.syncTimeout)
234+
defer cancel()
228235
// todo: use adc config
229236
serverAddr := d.ServerAddr
230237
if config.ServerAddr != "" {
@@ -244,7 +251,7 @@ func (d *adcClient) execADC(config adcConfig, args []string) error {
244251
}
245252

246253
var stdout, stderr bytes.Buffer
247-
cmd := exec.Command("adc", args...)
254+
cmd := exec.CommandContext(ctxWithTimeout, "adc", args...)
248255
cmd.Stdout = &stdout
249256
cmd.Stderr = &stderr
250257
cmd.Env = append(cmd.Env, os.Environ()...)

0 commit comments

Comments
 (0)